Skip to content

Node v12 #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# HTTP Parser

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.

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).

Jan Schär (jscissr) made some bigger changes and added tests. This fixed some bugs and added many missing features.
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.

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

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

## Status

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.
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.

### Node Versions

`http-parser-js` should work via monkey-patching on Node v6-v11, and v13.

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.

## License

Expand Down
11 changes: 10 additions & 1 deletion http-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ var assert = require('assert');

exports.HTTPParser = HTTPParser;
function HTTPParser(type) {
assert.ok(type === HTTPParser.REQUEST || type === HTTPParser.RESPONSE || type === undefined);
if (type === undefined) {
// Node v12+
} else {
this.initialize(type);
}
}
HTTPParser.prototype.initialize = function (type, async_resource) {
assert.ok(type === HTTPParser.REQUEST || type === HTTPParser.RESPONSE);
this.type = type;
this.state = type + '_LINE';
Expand All @@ -19,7 +27,8 @@ function HTTPParser(type) {
this.body_bytes = null;
this.isUserCall = false;
this.hadError = false;
}
};

HTTPParser.encoding = 'ascii';
HTTPParser.maxHeaderSize = 80 * 1024; // maxHeaderSize (in bytes) is configurable, but 80kb by default;
HTTPParser.REQUEST = 'REQUEST';
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "http-parser-js",
"version": "0.5.1",
"version": "0.5.2",
"description": "A pure JS HTTP parser for node.",
"main": "http-parser.js",
"scripts": {
"test": "python tests/test.py && node tests/iojs/test-http-parser-durability.js"
"test": "python tests/test.py && node tests/iojs/test-http-parser-durability.js",
"testv12": "python tests/test.py --node-args=\"--http-parser=legacy\" && node --http-parser=legacy tests/iojs/test-http-parser-durability.js"
},
"repository": {
"type": "git",
Expand Down
4 changes: 4 additions & 0 deletions tests/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ if (global.Symbol) {
knownGlobals.push(Symbol);
}

if (global.queueMicrotask) {
knownGlobals.push(queueMicrotask);
}

function leakedGlobals() {
var leaked = [];

Expand Down
45 changes: 45 additions & 0 deletions tests/parallel/test-http-chunked-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

require('../common');
var assert = require('assert');
var http = require('http');
var url = require('url');

var responses_sent = 0;
var responses_recvd = 0;
var body0 = '';
var body1 = '';

var server = http.Server(function(req, res) {
this.close();
req.on('end', function() {
res.writeHead(200, {'Content-Type': 'text/plain', 'Transfer-Encoding': 'chunked'});
res.write('some');
res.write('chunked');
res.write('data');
res.end();
});
req.resume();
});
server.listen(0);

server.on('listening', function() {
var agent = new http.Agent({ port: this.address().port, maxSockets: 1 });
http.get({
port: this.address().port,
path: '/hello',
headers: {'Accept': '*/*', 'Foo': 'bar'},
agent: agent
}, function(res) {
assert.equal(200, res.statusCode);
res.setEncoding('utf8');
res.on('data', function(chunk) { body0 += chunk; });
res.on('end', function () {
console.error('Got /hello response', body0);
});
});
});

process.on('exit', function() {
assert.equal('somechunkeddata', body0);
});
8 changes: 6 additions & 2 deletions tests/parallel/test-http-destroyed-socket-write2.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ server.listen(0, function() {
break;
}

assert.equal(req.output.length, 0);
assert.equal(req.outputEncodings.length, 0);
if (req.outputData) { // Node v12+
assert.strictEqual(req.outputData.length, 0);
} else {
assert.equal(req.output.length, 0);
assert.equal(req.outputEncodings.length, 0);
}
server.close();
}));

Expand Down
2 changes: 2 additions & 0 deletions tests/parallel/test-http-max-headers-count.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Note: If this test fails, monkey-patching probably failed and you're using
// the default Node parser, which now has a limit of 8KB for header data
'use strict';
require('../common');
var assert = require('assert');
Expand Down