Skip to content
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

Replace C HTTP parser with JS HTTP parser #1457

Closed
wants to merge 67 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
fc2378f
lib,src,deps: switch from C++ to JS HTTP parser
mscdex Apr 11, 2015
67b0e62
doc: update http documentation
mscdex Apr 11, 2015
6b0ead3
http: move variable declaration
mscdex Apr 11, 2015
9dd9560
http: improve parser performance
mscdex Apr 12, 2015
eb3d679
benchmark: add a variety of http parser benchmarks
mscdex Apr 12, 2015
4e37fcc
http: remove unused variable
mscdex Apr 12, 2015
fd6c127
http: fix max chunk size string len
mscdex Apr 12, 2015
6a1e157
http: use faster NaN check
mscdex Apr 12, 2015
2e63483
http: use faster hex number decoding
mscdex Apr 12, 2015
1ead648
benchmark: fix V8 warmup for http parser benchmarks
mscdex Apr 13, 2015
b254753
http: fix comment typo
mscdex Apr 13, 2015
2c4ebc2
benchmark: improve http parser benchmark more
mscdex Apr 14, 2015
f5ba8cf
http: style change
mscdex Apr 14, 2015
f4d786e
http: remove chunk size string length checking
mscdex Apr 16, 2015
455ea89
http: remove unused variable
mscdex Apr 16, 2015
237e8d5
http: allow double quotes and non-ASCII bytes in request URI
mscdex Apr 16, 2015
48e1dc7
http: improve comment wording
mscdex Apr 16, 2015
ade4029
http: improve comment wording (again)
mscdex Apr 16, 2015
d3b4976
http: fix parsing of authority portion of request URI
mscdex Apr 16, 2015
6ee84a8
http: fix parsing hier-part of request URI
mscdex Apr 16, 2015
766c731
http: fix whitespace preservation if folding is encountered
mscdex Apr 16, 2015
234864a
http: add extra internal state check in finish()
mscdex Apr 16, 2015
b59f4f1
http: fix keepalive check
mscdex Apr 16, 2015
a332c74
http: check for multiple values in Connection header value
mscdex Apr 16, 2015
9a7f8d5
http: ensure first byte is printable ASCII
mscdex Apr 16, 2015
ac584b9
http: return early if data chunk is empty
mscdex Apr 16, 2015
382b12c
http: remove duplicate code
mscdex Apr 16, 2015
8d5d474
http: add missing execute handler change
mscdex Apr 16, 2015
a5194be
http: fix typo
mscdex Apr 16, 2015
434e1bb
http: add missing ltrim function
mscdex Apr 16, 2015
6e0c6ba
http: lint and style changes
mscdex Apr 16, 2015
8d56d59
http: add misc notes about differences with joyent/http-parser
mscdex Apr 16, 2015
2728b9d
test: port main req/res tests from joyent/http-parser
mscdex Apr 16, 2015
f35d9dd
benchmark: style change
mscdex Apr 16, 2015
fb64bd1
http: reduce error setting boilerplate
mscdex Apr 16, 2015
9bc7d5c
http: use max js int value - 1 for content/chunk lengths
mscdex Apr 16, 2015
686ced1
http: remove unnecessary internal state variable
mscdex Apr 16, 2015
b53d285
http: lint
mscdex Apr 16, 2015
db67814
http: update parser header comments
mscdex Apr 17, 2015
7f8bf45
http: fix keepalive support
mscdex Apr 17, 2015
b0b0950
http: onBody needs byte count not offset for third argument
mscdex Apr 17, 2015
543afe7
http: return data length for non-keepalive literal body
mscdex Apr 17, 2015
05c3baa
test: port remaining joyent/http-parser tests
mscdex Apr 17, 2015
6b8afe5
http: remove unused variables
mscdex Apr 17, 2015
86b6bda
http: move keepalive boolean to flag
mscdex Apr 17, 2015
cfb7f3e
http: avoid parsing '1'/'0'
mscdex Apr 17, 2015
ae19bae
http: lint and style changes
mscdex Apr 17, 2015
6879858
http: reduce property lookups
mscdex Apr 17, 2015
f6c134f
build: another fixup after rebase
mscdex Apr 17, 2015
f5197ae
http: improve multi header value matching
mscdex Apr 18, 2015
ede7529
http: use null instead of undefined
mscdex Apr 18, 2015
61e1b0b
benchmark: add alternating inputs for http parser benchmarks
mscdex Apr 22, 2015
f7c90ff
test: move http parser durability test to pummel
mscdex Apr 22, 2015
05480ac
test: fix test to reflect lack of HTTP 0.9 support
mscdex Apr 22, 2015
c48053a
http: switch to regexp-less, LF-compatible js parser
mscdex Apr 22, 2015
b7ee346
http: fix comment style
mscdex Apr 22, 2015
d97942b
http: fix bad chunk size detection
mscdex Apr 22, 2015
79e2d60
http: avoid double request method traversal
mscdex Apr 23, 2015
526b24f
http: validate request url
mscdex Apr 24, 2015
950582a
test: fix typo
mscdex Apr 24, 2015
3a870f1
test: port URL tests from joyent/http-parser
mscdex Apr 24, 2015
d3247f1
http: move property initialization to prototype
mscdex Apr 25, 2015
fb32e80
http: check valid field name before checking range
mscdex Apr 25, 2015
4af63d7
http: switch to regexp search for longer field names
mscdex Apr 26, 2015
7ba6c2b
http: remove parser pause()/resume() usage
mscdex Apr 27, 2015
3da4427
test: update comment
mscdex Apr 28, 2015
d56a9f0
lib,test: fix lint issues
mscdex Jun 21, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 0 additions & 27 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,33 +186,6 @@ The externally maintained libraries used by io.js are:
*/
"""

- HTTP Parser, located at deps/http_parser. HTTP Parser's license follows:
"""
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
Igor Sysoev.

Additional changes are licensed under the same terms as NGINX and
copyright Joyent, Inc. and other Node contributors. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
"""

- Closure Linter is located at tools/closure_linter. Closure's license
follows:
"""
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ $(NODE_G_EXE): config.gypi out/Makefile
$(MAKE) -C out BUILDTYPE=Debug V=$(V)
ln -fs out/Debug/$(NODE_EXE) $@

out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp deps/zlib/zlib.gyp deps/v8/build/toolchain.gypi deps/v8/build/features.gypi deps/v8/tools/gyp/v8.gyp node.gyp config.gypi
out/Makefile: common.gypi deps/uv/uv.gyp deps/zlib/zlib.gyp deps/v8/build/toolchain.gypi deps/v8/build/features.gypi deps/v8/tools/gyp/v8.gyp node.gyp config.gypi
$(PYTHON) tools/gyp_node.py -f make

config.gypi: configure
Expand Down
1 change: 0 additions & 1 deletion Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ NACL_ARCHES = nacl_ia32 nacl_x64
GYPFILES = \
common.gypi \
deps/cares/cares.gyp \
deps/http_parser/http_parser.gyp \
deps/openssl/openssl.gyp \
deps/uv/uv.gyp \
deps/v8/tools/gyp/v8.gyp \
Expand Down
199 changes: 199 additions & 0 deletions benchmark/http/parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
var common = require('../common.js');
var HTTPParser = require('_http_parser');
var CRLF = '\r\n';
var REQUEST = HTTPParser.REQUEST;
var RESPONSE = HTTPParser.RESPONSE;

var bench = common.createBenchmark(main, {
n: [100000],
type: [
'small-req',
'small-res',
'small-alternate',
'medium-req',
'medium-res',
'medium-alternate',
'medium-req-chunked',
'medium-res-chunked',
'large-req',
'large-res',
'large-alternate',
'large-req-chunked',
'large-res-chunked',
]
});

var inputs = {
'small-req': [
'GET /index.html HTTP/1.1' + CRLF +
'Host: www.example.com' + CRLF + CRLF
],
'small-res': [
'HTTP/1.1 200 OK' + CRLF +
'Date: Mon, 23 May 2005 22:38:34 GMT' + CRLF + CRLF
],
'small-alternate': true,
'medium-req': [
'POST /it HTTP/1.1' + CRLF +
'Content-Type: text/plain' + CRLF +
'Transfer-Encoding: chunked' + CRLF +
CRLF +
'3' + CRLF +
'123' + CRLF +
'6' + CRLF +
'123456' + CRLF +
'A' + CRLF +
'1234567890' + CRLF +
'9' + CRLF +
'123456789' + CRLF +
'C' + CRLF +
'123456789ABC' + CRLF +
'F' + CRLF +
'123456789ABCDEF' + CRLF +
'0' + CRLF
],
'medium-res': [
'HTTP/1.0 200 OK' + CRLF +
'Date: Mon, 23 May 2005 22:38:34 GMT' + CRLF +
'Content-Type: text/plain' + CRLF +
'Transfer-Encoding: chunked' + CRLF +
CRLF +
'3' + CRLF +
'123' + CRLF +
'6' + CRLF +
'123456' + CRLF +
'A' + CRLF +
'1234567890' + CRLF +
'9' + CRLF +
'123456789' + CRLF +
'C' + CRLF +
'123456789ABC' + CRLF +
'F' + CRLF +
'123456789ABCDEF' + CRLF +
'0' + CRLF
],
'medium-alternate': true,
'medium-req-chunked': [
'POST /it HTTP/',
'1.1' + CRLF,
'Content-Type',
': text',
'/plain',
CRLF,
'Transfer-',
'Encoding: chunked' + CRLF,
CRLF + '3' + CRLF + '123',
CRLF + '6' + CRLF + '123456' + CRLF + 'A' + CRLF,
'12345',
'67890' + CRLF,
'9' + CRLF + '123456789' + CRLF,
'C' + CRLF + '123456789ABC' + CRLF + 'F' + CRLF + '123456789ABCDEF' + CRLF,
'0' + CRLF
],
'medium-res-chunked': [
'HTTP/1.0 2',
'00 OK' + CRLF + 'Date: Mo',
'n, 23 May 2005 22',
':38:34 GMT' + CRLF + 'Content-Type: text',
'/plain' + CRLF,
'Transfer-Encoding: chu',
'nked' + CRLF + CRLF + '3',
CRLF + '123' + CRLF + '6' + CRLF,
'123456' + CRLF + 'A' + CRLF + '1234567890' + CRLF,
'9' + CRLF,
'123456789' + CRLF,
'C' + CRLF,
'123456789ABC' + CRLF,
'F' + CRLF,
'123456789ABCDEF' + CRLF + '0' + CRLF
],
'large-req': [
'POST /foo/bar/baz?quux=42#1337 HTTP/1.0' + CRLF +
new Array(256).join('X-Filler: 42' + CRLF) + CRLF
],
'large-res': [
'HTTP/1.1 200 OK' + CRLF +
'Content-Type: text/nonsense' + CRLF,
'Content-Length: 3572' + CRLF + CRLF +
new Array(256).join('X-Filler: 42' + CRLF) + CRLF
],
'large-alternate': true,
'large-req-chunked':
('POST /foo/bar/baz?quux=42#1337 HTTP/1.0' + CRLF +
new Array(256).join('X-Filler: 42' + CRLF) + CRLF).match(/.{1,144}/g)
,
'large-res-chunked':
('HTTP/1.1 200 OK' + CRLF +
'Content-Type: text/nonsense' + CRLF,
'Content-Length: 3572' + CRLF + CRLF +
new Array(256).join('X-Filler: 42' + CRLF) + CRLF).match(/.{1,144}/g)
,
};

function onHeaders(versionMajor, versionMinor, headers, method, url, statusCode,
statusMessage, upgrade, shouldKeepAlive) {
}
function onBody(data, start, len) {
}
function onComplete() {
}

function main(conf) {
var type = conf.type;
var chunks = inputs[type];
var n = +conf.n;
var nchunks = (chunks !== true ? chunks.length : 1);
var kind = (/\-req\-?/i.exec(type) ? REQUEST : RESPONSE);
var altsize = /^([^\-]+)\-alternate$/.exec(type);
var req;
var res;

if (altsize)
altsize = altsize[1];

// Convert strings to Buffers first ...
if (chunks === true) {
// alternating
req = new Buffer(inputs[altsize + '-req'].join(''), 'binary');
res = new Buffer(inputs[altsize + '-res'].join(''), 'binary');
kind = REQUEST;
} else {
for (var i = 0; i < nchunks; ++i)
chunks[i] = new Buffer(chunks[i], 'binary');
}

var parser = new HTTPParser(kind);
parser.onHeaders = onHeaders;
parser.onBody = onBody;
parser.onComplete = onComplete;

if (altsize) {
// Allow V8 to optimize first ...
for (var j = 0; j < 1000; ++j) {
parser.reinitialize(REQUEST);
parser.execute(req);
parser.reinitialize(RESPONSE);
parser.execute(res);
}
bench.start();
for (var c = 0; c < n; ++c) {
parser.reinitialize(REQUEST);
parser.execute(req);
parser.reinitialize(RESPONSE);
parser.execute(res);
}
bench.end(n * 2);
} else {
// Allow V8 to optimize first ...
for (var j = 0; j < 1000; ++j) {
for (var i = 0; i < nchunks; ++i)
parser.execute(chunks[i]);
}
bench.start();
for (var c = 0; c < n; ++c) {
for (var i = 0; i < nchunks; ++i)
parser.execute(chunks[i]);
}
bench.end(n * nchunks);
}
}
22 changes: 0 additions & 22 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -93,27 +93,6 @@ parser.add_option('--openssl-fips',
dest='openssl_fips',
help='Build OpenSSL using FIPS canister .o file in supplied folder')

shared_optgroup.add_option('--shared-http-parser',
action='store_true',
dest='shared_http_parser',
help='link to a shared http_parser DLL instead of static linking')

shared_optgroup.add_option('--shared-http-parser-includes',
action='store',
dest='shared_http_parser_includes',
help='directory containing http_parser header files')

shared_optgroup.add_option('--shared-http-parser-libname',
action='store',
dest='shared_http_parser_libname',
default='http_parser',
help='alternative lib name to link to [default: %default]')

shared_optgroup.add_option('--shared-http-parser-libpath',
action='store',
dest='shared_http_parser_libpath',
help='a directory to search for the shared http_parser DLL')

shared_optgroup.add_option('--shared-libuv',
action='store_true',
dest='shared_libuv',
Expand Down Expand Up @@ -1017,7 +996,6 @@ flavor = GetFlavor(flavor_params)

configure_node(output)
configure_library('zlib', output)
configure_library('http_parser', output)
configure_library('libuv', output)
configure_v8(output)
configure_openssl(output)
Expand Down
28 changes: 0 additions & 28 deletions deps/http_parser/.gitignore

This file was deleted.

8 changes: 0 additions & 8 deletions deps/http_parser/.mailmap

This file was deleted.

13 changes: 0 additions & 13 deletions deps/http_parser/.travis.yml

This file was deleted.