forked from hapijs/shot
/
response.js
executable file
·106 lines (68 loc) · 2.68 KB
/
response.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
'use strict';
// Load modules
const Http = require('http');
const Util = require('util');
// Declare internals
const internals = {};
exports = module.exports = internals.Response = function (req, onEnd) {
Http.ServerResponse.call(this, { method: req.method, httpVersionMajor: 1, httpVersionMinor: 1 });
this.shot = { trailers: {}, payloadChunks: [] };
this.once('finish', () => {
const res = internals.payload(this);
res.raw.req = req;
process.nextTick(() => onEnd(res));
});
};
Util.inherits(internals.Response, Http.ServerResponse);
internals.Response.prototype.writeHead = function () {
const headers = ((arguments.length === 2 && typeof arguments[1] === 'object') ? arguments[1] : (arguments.length === 3 ? arguments[2] : {}));
const result = Http.ServerResponse.prototype.writeHead.apply(this, arguments);
this._headers = this._headers || {};
const keys = Object.keys(headers);
for (let i = 0; i < keys.length; ++i) {
this._headers[keys[i]] = headers[keys[i]];
}
// Add raw headers
['Date', 'Connection', 'Transfer-Encoding'].forEach((name) => {
const regex = new RegExp('\\r\\n' + name + ': ([^\\r]*)\\r\\n');
const field = this._header.match(regex);
if (field) {
this._headers[name.toLowerCase()] = field[1];
}
});
return result;
};
internals.Response.prototype.write = function (data, encoding) {
this.shot.payloadChunks.push(new Buffer(data, encoding));
Http.ServerResponse.prototype.write.call(this, data, encoding);
return true; // Write always returns false when disconnected
};
internals.Response.prototype.end = function (data, encoding) {
Http.ServerResponse.prototype.end.call(this, data, encoding);
this.emit('finish'); // Will not be emitted when disconnected
};
internals.Response.prototype.destroy = function () {
};
internals.Response.prototype.addTrailers = function (trailers) {
for (const key in trailers) {
this.shot.trailers[key.toLowerCase().trim()] = trailers[key].toString().trim();
}
};
internals.payload = function (response) {
// Prepare response object
const res = {
raw: {
res: response
},
headers: response._headers,
statusCode: response.statusCode,
statusMessage: response.statusMessage,
trailers: {}
};
// Prepare payload and trailers
const rawBuffer = Buffer.concat(response.shot.payloadChunks);
res.rawPayload = rawBuffer;
res.payload = rawBuffer.toString();
res.trailers = response.shot.trailers;
return res;
};