Skip to content

Commit c8d5e31

Browse files
addaleaxBridgeAR
authored andcommitted
http: make parser choice a runtime flag
Add a `--http-parser=llhttp` vs `--http-parser=traditional` command line switch, to make testing and comparing the new llhttp-based implementation easier. PR-URL: #24739 Refs: #24730 Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Matheus Marchini <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Ali Ijaz Sheikh <[email protected]>
1 parent a22ac0b commit c8d5e31

29 files changed

+157
-85
lines changed

configure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
parser.add_option('--experimental-http-parser',
188188
action='store_true',
189189
dest='experimental_http_parser',
190-
help='use llhttp instead of http_parser')
190+
help='use llhttp instead of http_parser by default')
191191

192192
shared_optgroup.add_option('--shared-http-parser',
193193
action='store_true',

doc/api/cli.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,22 @@ added: v6.0.0
119119
Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.)
120120
(Same requirements as `--enable-fips`.)
121121

122+
### `--http-parser=library`
123+
<!-- YAML
124+
added: REPLACEME
125+
-->
126+
127+
Chooses an HTTP parser library. Available values are:
128+
129+
- `llhttp` for https://llhttp.org/
130+
- `legacy` for https://github.com/nodejs/http-parser
131+
132+
The default is `legacy`, unless otherwise specified when building Node.js.
133+
134+
This flag exists to aid in experimentation with the internal implementation of
135+
the Node.js http parser.
136+
This flag is likely to become a no-op and removed at some point in the future.
137+
122138
### `--icu-data-dir=file`
123139
<!-- YAML
124140
added: v0.11.15

doc/node.1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ Enable experimental ES module support in VM module.
9797
.It Fl -experimental-worker
9898
Enable experimental worker threads using worker_threads module.
9999
.
100+
.It Fl -http-parser Ns = Ns Ar library
101+
Chooses an HTTP parser library. Available values are
102+
.Sy llhttp
103+
or
104+
.Sy legacy .
105+
.
100106
.It Fl -force-fips
101107
Force FIPS-compliant crypto on startup
102108
(Cannot be disabled from script code).

lib/_http_client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
const util = require('util');
2525
const net = require('net');
2626
const url = require('url');
27-
const { HTTPParser } = internalBinding('http_parser');
2827
const assert = require('assert').ok;
2928
const {
3029
_checkIsHttpToken: checkIsHttpToken,
3130
debug,
3231
freeParser,
3332
httpSocketSetup,
34-
parsers
33+
parsers,
34+
HTTPParser,
3535
} = require('_http_common');
3636
const { OutgoingMessage } = require('_http_outgoing');
3737
const Agent = require('_http_agent');

lib/_http_common.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121

2222
'use strict';
2323

24-
const { methods, HTTPParser } = internalBinding('http_parser');
24+
const { getOptionValue } = require('internal/options');
25+
26+
const { methods, HTTPParser } =
27+
getOptionValue('--http-parser') === 'legacy' ?
28+
internalBinding('http_parser') : internalBinding('http_parser_llhttp');
2529

2630
const { FreeList } = require('internal/freelist');
2731
const { ondrain } = require('internal/http');
@@ -243,5 +247,6 @@ module.exports = {
243247
httpSocketSetup,
244248
methods,
245249
parsers,
246-
kIncomingMessage
250+
kIncomingMessage,
251+
HTTPParser
247252
};

lib/_http_server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
const util = require('util');
2525
const net = require('net');
26-
const { HTTPParser } = internalBinding('http_parser');
2726
const assert = require('assert').ok;
2827
const {
2928
parsers,
@@ -34,6 +33,7 @@ const {
3433
chunkExpression,
3534
httpSocketSetup,
3635
kIncomingMessage,
36+
HTTPParser,
3737
_checkInvalidHeaderChar: checkInvalidHeaderChar
3838
} = require('_http_common');
3939
const { OutgoingMessage } = require('_http_outgoing');

lib/internal/child_process.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ const handleConversion = {
127127
if (freeParser === undefined)
128128
freeParser = require('_http_common').freeParser;
129129
if (HTTPParser === undefined)
130-
HTTPParser = internalBinding('http_parser').HTTPParser;
130+
HTTPParser = require('_http_common').HTTPParser;
131131

132132
// In case of an HTTP connection socket, release the associated
133133
// resources

node.gyp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,8 @@
352352
'src/node_encoding.cc',
353353
'src/node_errors.cc',
354354
'src/node_file.cc',
355-
'src/node_http_parser.cc',
355+
'src/node_http_parser_llhttp.cc',
356+
'src/node_http_parser_traditional.cc',
356357
'src/node_http2.cc',
357358
'src/node_i18n.cc',
358359
'src/node_messaging.cc',
@@ -423,6 +424,7 @@
423424
'src/node_contextify.h',
424425
'src/node_errors.h',
425426
'src/node_file.h',
427+
'src/node_http_parser_impl.h',
426428
'src/node_http2.h',
427429
'src/node_http2_state.h',
428430
'src/node_i18n.h',

node.gypi

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,14 @@
164164
}],
165165

166166
[ 'node_experimental_http_parser=="true"', {
167-
'defines': [ 'NODE_EXPERIMENTAL_HTTP' ],
168-
'dependencies': [ 'deps/llhttp/llhttp.gyp:llhttp' ],
169-
}, {
170-
'conditions': [ [ 'node_shared_http_parser=="false"', {
171-
'dependencies': [ 'deps/http_parser/http_parser.gyp:http_parser' ],
172-
} ] ],
167+
'defines': [ 'NODE_EXPERIMENTAL_HTTP_DEFAULT' ],
168+
} ],
169+
170+
[ 'node_shared_http_parser=="false"', {
171+
'dependencies': [
172+
'deps/http_parser/http_parser.gyp:http_parser',
173+
'deps/llhttp/llhttp.gyp:llhttp'
174+
],
173175
} ],
174176

175177
[ 'node_shared_cares=="false"', {

src/inspector_socket.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include "inspector_socket.h"
22

3+
#ifdef NODE_EXPERIMENTAL_HTTP_DEFAULT
4+
#define NODE_EXPERIMENTAL_HTTP
5+
#endif
36
#include "http_parser_adaptor.h"
7+
48
#include "util-inl.h"
59

610
#define NODE_WANT_INTERNALS 1
@@ -433,13 +437,13 @@ class HttpHandler : public ProtocolHandler {
433437
explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
434438
: ProtocolHandler(inspector, std::move(tcp)),
435439
parsing_value_(false) {
436-
#ifdef NODE_EXPERIMENTAL_HTTP
440+
#ifdef NODE_EXPERIMENTAL_HTTP_DEFAULT
437441
llhttp_init(&parser_, HTTP_REQUEST, &parser_settings);
438442
llhttp_settings_init(&parser_settings);
439-
#else /* !NODE_EXPERIMENTAL_HTTP */
443+
#else /* !NODE_EXPERIMENTAL_HTTP_DEFAULT */
440444
http_parser_init(&parser_, HTTP_REQUEST);
441445
http_parser_settings_init(&parser_settings);
442-
#endif /* NODE_EXPERIMENTAL_HTTP */
446+
#endif /* NODE_EXPERIMENTAL_HTTP_DEFAULT */
443447
parser_settings.on_header_field = OnHeaderField;
444448
parser_settings.on_header_value = OnHeaderValue;
445449
parser_settings.on_message_complete = OnMessageComplete;
@@ -484,17 +488,17 @@ class HttpHandler : public ProtocolHandler {
484488

485489
void OnData(std::vector<char>* data) override {
486490
parser_errno_t err;
487-
#ifdef NODE_EXPERIMENTAL_HTTP
491+
#ifdef NODE_EXPERIMENTAL_HTTP_DEFAULT
488492
err = llhttp_execute(&parser_, data->data(), data->size());
489493

490494
if (err == HPE_PAUSED_UPGRADE) {
491495
err = HPE_OK;
492496
llhttp_resume_after_upgrade(&parser_);
493497
}
494-
#else /* !NODE_EXPERIMENTAL_HTTP */
498+
#else /* !NODE_EXPERIMENTAL_HTTP_DEFAULT */
495499
http_parser_execute(&parser_, &parser_settings, data->data(), data->size());
496500
err = HTTP_PARSER_ERRNO(&parser_);
497-
#endif /* NODE_EXPERIMENTAL_HTTP */
501+
#endif /* NODE_EXPERIMENTAL_HTTP_DEFAULT */
498502
data->clear();
499503
if (err != HPE_OK) {
500504
CancelHandshake();

0 commit comments

Comments
 (0)