1
|
var assert = require('assert');
|
2
|
var util = require('util');
|
3
|
|
4
|
var Buffer = require('buffer').Buffer;
|
5
|
|
6
|
// Node.js version
|
7
|
var mode = /^v0\.8\./.test(process.version) ? 'rusty' :
|
8
|
/^v0\.(9|10)\./.test(process.version) ? 'old' :
|
9
|
/^v0\.12\./.test(process.version) ? 'normal' :
|
10
|
'modern';
|
11
|
|
12
|
var HTTPParser;
|
13
|
|
14
|
var methods;
|
15
|
var reverseMethods;
|
16
|
|
17
|
var kOnHeaders;
|
18
|
var kOnHeadersComplete;
|
19
|
var kOnMessageComplete;
|
20
|
var kOnBody;
|
21
|
if (mode === 'normal' || mode === 'modern') {
|
22
|
HTTPParser = process.binding('http_parser').HTTPParser;
|
23
|
methods = HTTPParser.methods;
|
24
|
|
25
|
// v6
|
26
|
if (!methods)
|
27
|
methods = process.binding('http_parser').methods;
|
28
|
|
29
|
reverseMethods = {};
|
30
|
|
31
|
methods.forEach(function(method, index) {
|
32
|
reverseMethods[method] = index;
|
33
|
});
|
34
|
|
35
|
kOnHeaders = HTTPParser.kOnHeaders | 0;
|
36
|
kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
|
37
|
kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
|
38
|
kOnBody = HTTPParser.kOnBody | 0;
|
39
|
} else {
|
40
|
kOnHeaders = 'onHeaders';
|
41
|
kOnHeadersComplete = 'onHeadersComplete';
|
42
|
kOnMessageComplete = 'onMessageComplete';
|
43
|
kOnBody = 'onBody';
|
44
|
}
|
45
|
|
46
|
function Deceiver(socket, options) {
|
47
|
this.socket = socket;
|
48
|
this.options = options || {};
|
49
|
this.isClient = this.options.isClient;
|
50
|
}
|
51
|
module.exports = Deceiver;
|
52
|
|
53
|
Deceiver.create = function create(stream, options) {
|
54
|
return new Deceiver(stream, options);
|
55
|
};
|
56
|
|
57
|
Deceiver.prototype._toHeaderList = function _toHeaderList(object) {
|
58
|
var out = [];
|
59
|
var keys = Object.keys(object);
|
60
|
|
61
|
for (var i = 0; i < keys.length; i++)
|
62
|
out.push(keys[i], object[keys[i]]);
|
63
|
|
64
|
return out;
|
65
|
};
|
66
|
|
67
|
Deceiver.prototype._isUpgrade = function _isUpgrade(request) {
|
68
|
return request.method === 'CONNECT' ||
|
69
|
request.headers.upgrade ||
|
70
|
request.headers.connection &&
|
71
|
/(^|\W)upgrade(\W|$)/i.test(request.headers.connection);
|
72
|
};
|
73
|
|
74
|
// TODO(indutny): support CONNECT
|
75
|
if (mode === 'modern') {
|
76
|
/*
|
77
|
function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
|
78
|
url, statusCode, statusMessage, upgrade,
|
79
|
shouldKeepAlive) {
|
80
|
*/
|
81
|
Deceiver.prototype.emitRequest = function emitRequest(request) {
|
82
|
var parser = this.socket.parser;
|
83
|
assert(parser, 'No parser present');
|
84
|
|
85
|
parser.execute = null;
|
86
|
|
87
|
var self = this;
|
88
|
var method = reverseMethods[request.method];
|
89
|
parser.execute = function execute() {
|
90
|
self._skipExecute(this);
|
91
|
this[kOnHeadersComplete](1,
|
92
|
1,
|
93
|
self._toHeaderList(request.headers),
|
94
|
method,
|
95
|
request.path,
|
96
|
0,
|
97
|
'',
|
98
|
self._isUpgrade(request),
|
99
|
true);
|
100
|
return 0;
|
101
|
};
|
102
|
|
103
|
this._emitEmpty();
|
104
|
};
|
105
|
|
106
|
Deceiver.prototype.emitResponse = function emitResponse(response) {
|
107
|
var parser = this.socket.parser;
|
108
|
assert(parser, 'No parser present');
|
109
|
|
110
|
parser.execute = null;
|
111
|
|
112
|
var self = this;
|
113
|
parser.execute = function execute() {
|
114
|
self._skipExecute(this);
|
115
|
this[kOnHeadersComplete](1,
|
116
|
1,
|
117
|
self._toHeaderList(response.headers),
|
118
|
response.path,
|
119
|
response.code,
|
120
|
response.status,
|
121
|
response.reason || '',
|
122
|
self._isUpgrade(response),
|
123
|
true);
|
124
|
return 0;
|
125
|
};
|
126
|
|
127
|
this._emitEmpty();
|
128
|
};
|
129
|
} else {
|
130
|
/*
|
131
|
`function parserOnHeadersComplete(info) {`
|
132
|
|
133
|
info = { .versionMajor, .versionMinor, .url, .headers, .method,
|
134
|
.statusCode, .statusMessage, .upgrade, .shouldKeepAlive }
|
135
|
*/
|
136
|
Deceiver.prototype.emitRequest = function emitRequest(request) {
|
137
|
var parser = this.socket.parser;
|
138
|
assert(parser, 'No parser present');
|
139
|
|
140
|
var method = request.method;
|
141
|
if (reverseMethods)
|
142
|
method = reverseMethods[method];
|
143
|
|
144
|
var info = {
|
145
|
versionMajor: 1,
|
146
|
versionMinor: 1,
|
147
|
url: request.path,
|
148
|
headers: this._toHeaderList(request.headers),
|
149
|
method: method,
|
150
|
statusCode: 0,
|
151
|
statusMessage: '',
|
152
|
upgrade: this._isUpgrade(request),
|
153
|
shouldKeepAlive: true
|
154
|
};
|
155
|
|
156
|
var self = this;
|
157
|
parser.execute = function execute() {
|
158
|
self._skipExecute(this);
|
159
|
this[kOnHeadersComplete](info);
|
160
|
return 0;
|
161
|
};
|
162
|
|
163
|
this._emitEmpty();
|
164
|
};
|
165
|
|
166
|
Deceiver.prototype.emitResponse = function emitResponse(response) {
|
167
|
var parser = this.socket.parser;
|
168
|
assert(parser, 'No parser present');
|
169
|
|
170
|
var info = {
|
171
|
versionMajor: 1,
|
172
|
versionMinor: 1,
|
173
|
url: response.path,
|
174
|
headers: this._toHeaderList(response.headers),
|
175
|
method: false,
|
176
|
statusCode: response.status,
|
177
|
statusMessage: response.reason || '',
|
178
|
upgrade: this._isUpgrade(response),
|
179
|
shouldKeepAlive: true
|
180
|
};
|
181
|
|
182
|
var self = this;
|
183
|
parser.execute = function execute() {
|
184
|
self._skipExecute(this);
|
185
|
this[kOnHeadersComplete](info);
|
186
|
return 0;
|
187
|
};
|
188
|
|
189
|
this._emitEmpty();
|
190
|
};
|
191
|
}
|
192
|
|
193
|
Deceiver.prototype._skipExecute = function _skipExecute(parser) {
|
194
|
var self = this;
|
195
|
var oldExecute = parser.constructor.prototype.execute;
|
196
|
var oldFinish = parser.constructor.prototype.finish;
|
197
|
|
198
|
parser.execute = null;
|
199
|
parser.finish = null;
|
200
|
|
201
|
parser.execute = function execute(buffer, start, len) {
|
202
|
// Parser reuse
|
203
|
if (this.socket !== self.socket) {
|
204
|
this.execute = oldExecute;
|
205
|
this.finish = oldFinish;
|
206
|
return this.execute(buffer, start, len);
|
207
|
}
|
208
|
|
209
|
if (start !== undefined)
|
210
|
buffer = buffer.slice(start, start + len);
|
211
|
self.emitBody(buffer);
|
212
|
return len;
|
213
|
};
|
214
|
|
215
|
parser.finish = function finish() {
|
216
|
// Parser reuse
|
217
|
if (this.socket !== self.socket) {
|
218
|
this.execute = oldExecute;
|
219
|
this.finish = oldFinish;
|
220
|
return this.finish();
|
221
|
}
|
222
|
|
223
|
this.execute = oldExecute;
|
224
|
this.finish = oldFinish;
|
225
|
self.emitMessageComplete();
|
226
|
};
|
227
|
};
|
228
|
|
229
|
Deceiver.prototype.emitBody = function emitBody(buffer) {
|
230
|
var parser = this.socket.parser;
|
231
|
assert(parser, 'No parser present');
|
232
|
|
233
|
parser[kOnBody](buffer, 0, buffer.length);
|
234
|
};
|
235
|
|
236
|
Deceiver.prototype._emitEmpty = function _emitEmpty() {
|
237
|
// Emit data to force out handling of UPGRADE
|
238
|
var empty = new Buffer(0);
|
239
|
if (this.socket.ondata)
|
240
|
this.socket.ondata(empty, 0, 0);
|
241
|
else
|
242
|
this.socket.emit('data', empty);
|
243
|
};
|
244
|
|
245
|
Deceiver.prototype.emitMessageComplete = function emitMessageComplete() {
|
246
|
var parser = this.socket.parser;
|
247
|
assert(parser, 'No parser present');
|
248
|
|
249
|
parser[kOnMessageComplete]();
|
250
|
};
|