Skip to content

Commit cfc5ece

Browse files
authored
Merge pull request #67 from creationix/node_v12
Update to support Node v12+ Note: on Node v12, you just run node with --http-parser=legacy in order to enable monkey-patching.
2 parents c6dff75 + c633c20 commit cfc5ece

7 files changed

+78
-11
lines changed

README.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# HTTP Parser
22

3-
This library parses HTTP protocol for requests and responses. It was created to replace `http_parser.c` since calling C++ function from JS is really slow in V8.
4-
5-
This was further modified by Jimbly to be useable in parsing responses, specifically tested with the "request" module, and addresses issues such as corrupt HTTP headers, which would otherwise cause Node's parser to throw a fatal error (HPE_INVALID_HEADER_TOKEN).
6-
7-
Jan Schär (jscissr) made some bigger changes and added tests. This fixed some bugs and added many missing features.
3+
This library parses HTTP protocol for requests and responses. It was created to replace `http_parser.c` since calling C++ function from JS is really slow in V8. However, it is now primarily useful in having a more flexible/tolerant HTTP parser when dealing with legacy services that do not meet the strict HTTP parsing rules Node's parser follows.
84

95
This is packaged as a standalone npm module. To use in node, monkeypatch HTTPParser.
106

@@ -22,7 +18,13 @@ Simply do `npm test`. The tests are copied from node and mscedex/io.js, with som
2218

2319
## Status
2420

25-
This should now be usable in any node application, it now supports (nearly) everything `http_parser.c` does while still being tolerant with corrupted headers.
21+
This should now be usable in any node application, it now supports (nearly) everything `http_parser.c` does while still being tolerant with corrupted headers, and other kinds of malformed data.
22+
23+
### Node Versions
24+
25+
`http-parser-js` should work via monkey-patching on Node v6-v11, and v13.
26+
27+
Node v12.x renamed the internal http parser, and did not expose it for monkey-patching, so to be able to monkey-patch on Node v12, you must run `node --http-parser=legacy file.js` to opt in to the old, monkey-patchable http_parser binding.
2628

2729
## License
2830

http-parser.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ var assert = require('assert');
44

55
exports.HTTPParser = HTTPParser;
66
function HTTPParser(type) {
7+
assert.ok(type === HTTPParser.REQUEST || type === HTTPParser.RESPONSE || type === undefined);
8+
if (type === undefined) {
9+
// Node v12+
10+
} else {
11+
this.initialize(type);
12+
}
13+
}
14+
HTTPParser.prototype.initialize = function (type, async_resource) {
715
assert.ok(type === HTTPParser.REQUEST || type === HTTPParser.RESPONSE);
816
this.type = type;
917
this.state = type + '_LINE';
@@ -19,7 +27,8 @@ function HTTPParser(type) {
1927
this.body_bytes = null;
2028
this.isUserCall = false;
2129
this.hadError = false;
22-
}
30+
};
31+
2332
HTTPParser.encoding = 'ascii';
2433
HTTPParser.maxHeaderSize = 80 * 1024; // maxHeaderSize (in bytes) is configurable, but 80kb by default;
2534
HTTPParser.REQUEST = 'REQUEST';

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
{
22
"name": "http-parser-js",
3-
"version": "0.5.1",
3+
"version": "0.5.2",
44
"description": "A pure JS HTTP parser for node.",
55
"main": "http-parser.js",
66
"scripts": {
7-
"test": "python tests/test.py && node tests/iojs/test-http-parser-durability.js"
7+
"test": "python tests/test.py && node tests/iojs/test-http-parser-durability.js",
8+
"testv12": "python tests/test.py --node-args=\"--http-parser=legacy\" && node --http-parser=legacy tests/iojs/test-http-parser-durability.js"
89
},
910
"repository": {
1011
"type": "git",

tests/common.js

+4
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ if (global.Symbol) {
343343
knownGlobals.push(Symbol);
344344
}
345345

346+
if (global.queueMicrotask) {
347+
knownGlobals.push(queueMicrotask);
348+
}
349+
346350
function leakedGlobals() {
347351
var leaked = [];
348352

tests/parallel/test-http-chunked-2.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict';
2+
3+
require('../common');
4+
var assert = require('assert');
5+
var http = require('http');
6+
var url = require('url');
7+
8+
var responses_sent = 0;
9+
var responses_recvd = 0;
10+
var body0 = '';
11+
var body1 = '';
12+
13+
var server = http.Server(function(req, res) {
14+
this.close();
15+
req.on('end', function() {
16+
res.writeHead(200, {'Content-Type': 'text/plain', 'Transfer-Encoding': 'chunked'});
17+
res.write('some');
18+
res.write('chunked');
19+
res.write('data');
20+
res.end();
21+
});
22+
req.resume();
23+
});
24+
server.listen(0);
25+
26+
server.on('listening', function() {
27+
var agent = new http.Agent({ port: this.address().port, maxSockets: 1 });
28+
http.get({
29+
port: this.address().port,
30+
path: '/hello',
31+
headers: {'Accept': '*/*', 'Foo': 'bar'},
32+
agent: agent
33+
}, function(res) {
34+
assert.equal(200, res.statusCode);
35+
res.setEncoding('utf8');
36+
res.on('data', function(chunk) { body0 += chunk; });
37+
res.on('end', function () {
38+
console.error('Got /hello response', body0);
39+
});
40+
});
41+
});
42+
43+
process.on('exit', function() {
44+
assert.equal('somechunkeddata', body0);
45+
});

tests/parallel/test-http-destroyed-socket-write2.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ server.listen(0, function() {
4747
break;
4848
}
4949

50-
assert.equal(req.output.length, 0);
51-
assert.equal(req.outputEncodings.length, 0);
50+
if (req.outputData) { // Node v12+
51+
assert.strictEqual(req.outputData.length, 0);
52+
} else {
53+
assert.equal(req.output.length, 0);
54+
assert.equal(req.outputEncodings.length, 0);
55+
}
5256
server.close();
5357
}));
5458

tests/parallel/test-http-max-headers-count.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Note: If this test fails, monkey-patching probably failed and you're using
2+
// the default Node parser, which now has a limit of 8KB for header data
13
'use strict';
24
require('../common');
35
var assert = require('assert');

0 commit comments

Comments
 (0)