Giter VIP home page Giter VIP logo

llhttp's Introduction

llhttp

CI

Port of http_parser to llparse.

Why?

Let's face it, http_parser is practically unmaintainable. Even introduction of a single new method results in a significant code churn.

This project aims to:

  • Make it maintainable
  • Verifiable
  • Improving benchmarks where possible

More details in Fedor Indutny's talk at JSConf EU 2019

How?

Over time, different approaches for improving http_parser's code base were tried. However, all of them failed due to resulting significant performance degradation.

This project is a port of http_parser to TypeScript. llparse is used to generate the output C source file, which could be compiled and linked with the embedder's program (like Node.js).

Performance

So far llhttp outperforms http_parser:

input size bandwidth reqs/sec time
llhttp 8192.00 mb 1777.24 mb/s 3583799.39 req/sec 4.61 s
http_parser 8192.00 mb 694.66 mb/s 1406180.33 req/sec 11.79 s

llhttp is faster by approximately 156%.

Maintenance

llhttp project has about 1400 lines of TypeScript code describing the parser itself and around 450 lines of C code and headers providing the helper methods. The whole http_parser is implemented in approximately 2500 lines of C, and 436 lines of headers.

All optimizations and multi-character matching in llhttp are generated automatically, and thus doesn't add any extra maintenance cost. On the contrary, most of http_parser's code is hand-optimized and unrolled. Instead describing "how" it should parse the HTTP requests/responses, a maintainer should implement the new features in http_parser cautiously, considering possible performance degradation and manually optimizing the new code.

Verification

The state machine graph is encoded explicitly in llhttp. The llparse automatically checks the graph for absence of loops and correct reporting of the input ranges (spans) like header names and values. In the future, additional checks could be performed to get even stricter verification of the llhttp.

Usage

#include "stdio.h"
#include "llhttp.h"
#include "string.h"

int handle_on_message_complete(llhttp_t* parser) {
	fprintf(stdout, "Message completed!\n");
	return 0;
}

int main() {
	llhttp_t parser;
	llhttp_settings_t settings;

	/*Initialize user callbacks and settings */
	llhttp_settings_init(&settings);

	/*Set user callback */
	settings.on_message_complete = handle_on_message_complete;

	/*Initialize the parser in HTTP_BOTH mode, meaning that it will select between
	*HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
	*input.
	*/
	llhttp_init(&parser, HTTP_BOTH, &settings);

	/*Parse request! */
	const char* request = "GET / HTTP/1.1\r\n\r\n";
	int request_len = strlen(request);

	enum llhttp_errno err = llhttp_execute(&parser, request, request_len);
	if (err == HPE_OK) {
		fprintf(stdout, "Successfully parsed!\n");
	} else {
		fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err), parser.reason);
	}
}

For more information on API usage, please refer to src/native/api.h.

API

llhttp_settings_t

The settings object contains a list of callbacks that the parser will invoke.

The following callbacks can return 0 (proceed normally), -1 (error) or HPE_PAUSED (pause the parser):

  • on_message_begin: Invoked when a new request/response starts.
  • on_message_complete: Invoked when a request/response has been completedly parsed.
  • on_url_complete: Invoked after the URL has been parsed.
  • on_method_complete: Invoked after the HTTP method has been parsed.
  • on_version_complete: Invoked after the HTTP version has been parsed.
  • on_status_complete: Invoked after the status code has been parsed.
  • on_header_field_complete: Invoked after a header name has been parsed.
  • on_header_value_complete: Invoked after a header value has been parsed.
  • on_chunk_header: Invoked after a new chunk is started. The current chunk length is stored in parser->content_length.
  • on_chunk_extension_name_complete: Invoked after a chunk extension name is started.
  • on_chunk_extension_value_complete: Invoked after a chunk extension value is started.
  • on_chunk_complete: Invoked after a new chunk is received.
  • on_reset: Invoked after on_message_complete and before on_message_begin when a new message is received on the same parser. This is not invoked for the first message of the parser.

The following callbacks can return 0 (proceed normally), -1 (error) or HPE_USER (error from the callback):

  • on_url: Invoked when another character of the URL is received.
  • on_status: Invoked when another character of the status is received.
  • on_method: Invoked when another character of the method is received. When parser is created with HTTP_BOTH and the input is a response, this also invoked for the sequence HTTP/ of the first message.
  • on_version: Invoked when another character of the version is received.
  • on_header_field: Invoked when another character of a header name is received.
  • on_header_value: Invoked when another character of a header value is received.
  • on_chunk_extension_name: Invoked when another character of a chunk extension name is received.
  • on_chunk_extension_value: Invoked when another character of a extension value is received.

The callback on_headers_complete, invoked when headers are completed, can return:

  • 0: Proceed normally.
  • 1: Assume that request/response has no body, and proceed to parsing the next message.
  • 2: Assume absence of body (as above) and make llhttp_execute() return HPE_PAUSED_UPGRADE.
  • -1: Error
  • HPE_PAUSED: Pause the parser.

void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings)

Initialize the parser with specific type and user settings.

uint8_t llhttp_get_type(llhttp_t* parser)

Returns the type of the parser.

uint8_t llhttp_get_http_major(llhttp_t* parser)

Returns the major version of the HTTP protocol of the current request/response.

uint8_t llhttp_get_http_minor(llhttp_t* parser)

Returns the minor version of the HTTP protocol of the current request/response.

uint8_t llhttp_get_method(llhttp_t* parser)

Returns the method of the current request.

int llhttp_get_status_code(llhttp_t* parser)

Returns the method of the current response.

uint8_t llhttp_get_upgrade(llhttp_t* parser)

Returns 1 if request includes the Connection: upgrade header.

void llhttp_reset(llhttp_t* parser)

Reset an already initialized parser back to the start state, preserving the existing parser type, callback settings, user data, and lenient flags.

void llhttp_settings_init(llhttp_settings_t* settings)

Initialize the settings object.

llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len)

Parse full or partial request/response, invoking user callbacks along the way.

If any of llhttp_data_cb returns errno not equal to HPE_OK - the parsing interrupts, and such errno is returned from llhttp_execute(). If HPE_PAUSED was used as a errno, the execution can be resumed with llhttp_resume() call.

In a special case of CONNECT/Upgrade request/response HPE_PAUSED_UPGRADE is returned after fully parsing the request/response. If the user wishes to continue parsing, they need to invoke llhttp_resume_after_upgrade().

if this function ever returns a non-pause type error, it will continue to return the same error upon each successive call up until llhttp_init() is called.

llhttp_errno_t llhttp_finish(llhttp_t* parser)

This method should be called when the other side has no further bytes to send (e.g. shutdown of readable side of the TCP connection.)

Requests without Content-Length and other messages might require treating all incoming bytes as the part of the body, up to the last byte of the connection.

This method will invoke on_message_complete() callback if the request was terminated safely. Otherwise a error code would be returned.

int llhttp_message_needs_eof(const llhttp_t* parser)

Returns 1 if the incoming message is parsed until the last byte, and has to be completed by calling llhttp_finish() on EOF.

int llhttp_should_keep_alive(const llhttp_t* parser)

Returns 1 if there might be any other messages following the last that was successfully parsed.

void llhttp_pause(llhttp_t* parser)

Make further calls of llhttp_execute() return HPE_PAUSED and set appropriate error reason.

Do not call this from user callbacks! User callbacks must return HPE_PAUSED if pausing is required.

void llhttp_resume(llhttp_t* parser)

Might be called to resume the execution after the pause in user's callback.

See llhttp_execute() above for details.

Call this only if llhttp_execute() returns HPE_PAUSED.

void llhttp_resume_after_upgrade(llhttp_t* parser)

Might be called to resume the execution after the pause in user's callback. See llhttp_execute() above for details.

Call this only if llhttp_execute() returns HPE_PAUSED_UPGRADE

llhttp_errno_t llhttp_get_errno(const llhttp_t* parser)

Returns the latest error.

const char* llhttp_get_error_reason(const llhttp_t* parser)

Returns the verbal explanation of the latest returned error.

User callback should set error reason when returning the error. See llhttp_set_error_reason() for details.

void llhttp_set_error_reason(llhttp_t* parser, const char* reason)

Assign verbal description to the returned error. Must be called in user callbacks right before returning the errno.

HPE_USER error code might be useful in user callbacks.

const char* llhttp_get_error_pos(const llhttp_t* parser)

Returns the pointer to the last parsed byte before the returned error. The pointer is relative to the data argument of llhttp_execute().

This method might be useful for counting the number of parsed bytes.

const char* llhttp_errno_name(llhttp_errno_t err)

Returns textual name of error code.

const char* llhttp_method_name(llhttp_method_t method)

Returns textual name of HTTP method.

const char* llhttp_status_name(llhttp_status_t status)

Returns textual name of HTTP status.

void llhttp_set_lenient_headers(llhttp_t* parser, int enabled)

Enables/disables lenient header value parsing (disabled by default). Lenient parsing disables header value token checks, extending llhttp's protocol support to highly non-compliant clients/server.

No HPE_INVALID_HEADER_TOKEN will be raised for incorrect header values when lenient parsing is "on".

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled)

Enables/disables lenient handling of conflicting Transfer-Encoding and Content-Length headers (disabled by default).

Normally llhttp would error when Transfer-Encoding is present in conjunction with Content-Length.

This error is important to prevent HTTP request smuggling, but may be less desirable for small number of cases involving legacy servers.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled)

Enables/disables lenient handling of Connection: close and HTTP/1.0 requests responses.

Normally llhttp would error the HTTP request/response after the request/response with Connection: close and Content-Length.

This is important to prevent cache poisoning attacks, but might interact badly with outdated and insecure clients.

With this flag the extra request/response will be parsed normally.

Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!

void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled)

Enables/disables lenient handling of Transfer-Encoding header.

Normally llhttp would error when a Transfer-Encoding has chunked value and another value after it (either in a single header or in multiple headers whose value are internally joined using , ).

This is mandated by the spec to reliably determine request body size and thus avoid request smuggling.

With this flag the extra value will be parsed normally.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_version(llhttp_t* parser, int enabled)

Enables/disables lenient handling of HTTP version.

Normally llhttp would error when the HTTP version in the request or status line is not 0.9, 1.0, 1.1 or 2.0. With this flag the extra value will be parsed normally.

Enabling this flag can pose a security issue since you will allow unsupported HTTP versions. USE WITH CAUTION!

void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled)

Enables/disables lenient handling of additional data received after a message ends and keep-alive is disabled.

Normally llhttp would error when additional unexpected data is received if the message contains the Connection header with close value. With this flag the extra data will discarded without throwing an error.

Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!

void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled)

Enables/disables lenient handling of incomplete CRLF sequences.

Normally llhttp would error when a CR is not followed by LF when terminating the request line, the status line, the headers or a chunk header. With this flag only a CR is required to terminate such sections.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled)

Enables/disables lenient handling of line separators.

Normally llhttp would error when a LF is not preceded by CR when terminating the request line, the status line, the headers, a chunk header or a chunk data. With this flag only a LF is required to terminate such sections.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled)

Enables/disables lenient handling of chunks not separated via CRLF.

Normally llhttp would error when after a chunk data a CRLF is missing before starting a new chunk. With this flag the new chunk can start immediately after the previous one.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled)

Enables/disables lenient handling of spaces after chunk size.

Normally llhttp would error when after a chunk size is followed by one or more spaces are present instead of a CRLF or ;. With this flag this check is disabled.

Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!

Build Instructions

Make sure you have Node.js, npm and npx installed. Then under project directory run:

npm ci
make

Bindings to other languages

Using with CMake

If you want to use this library in a CMake project as a shared library, you can use the snippet below.

FetchContent_Declare(llhttp
  URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz")

FetchContent_MakeAvailable(llhttp)

# Link with the llhttp_shared target
target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_shared ${PROJECT_NAME})

If you want to use this library in a CMake project as a static library, you can set some cache variables first.

FetchContent_Declare(llhttp
  URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz")

set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
set(BUILD_STATIC_LIBS ON CACHE INTERNAL "")
FetchContent_MakeAvailable(llhttp)

# Link with the llhttp_static target
target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_static ${PROJECT_NAME})

Note that using the git repo directly (e.g., via a git repo url and tag) will not work with FetchContent_Declare because CMakeLists.txt requires string replacements (e.g., _RELEASE_) before it will build.

Building on Windows

Installation

  • choco install git
  • choco install node
  • choco install llvm (or install the C++ Clang tools for Windows optional package from the Visual Studio 2019 installer)
  • choco install make (or if you have MinGW, it comes bundled)
  1. Ensure that Clang and make are in your system path.
  2. Using Git Bash, clone the repo to your preferred location.
  3. Cd into the cloned directory and run npm ci
  4. Run make
  5. Your repo/build directory should now have libllhttp.a and libllhttp.so static and dynamic libraries.
  6. When building your executable, you can link to these libraries. Make sure to set the build folder as an include path when building so you can reference the declarations in repo/build/llhttp.h.

A simple example on linking with the library:

Assuming you have an executable main.cpp in your current working directory, you would run: clang++ -Os -g3 -Wall -Wextra -Wno-unused-parameter -I/path/to/llhttp/build main.cpp /path/to/llhttp/build/libllhttp.a -o main.exe.

If you are getting unresolved external symbol linker errors you are likely attempting to build llhttp.c without linking it with object files from api.c and http.c.

LICENSE

This software is licensed under the MIT License.

Copyright Fedor Indutny, 2018.

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.

llhttp's People

Contributors

0xflotus avatar arlen-lt avatar bdraco avatar bsergean avatar davidhcefx avatar dependabot[bot] avatar dreamsorcerer avatar fanatid avatar indutny avatar jacksontian avatar lukiano avatar marco-ippolito avatar mcollina avatar mhdawson avatar muniftanjim avatar musicinmybrain avatar ngrodzitski avatar pallas avatar rafaelgss avatar richardlau avatar ronag avatar scadgek avatar sgallagher avatar shogunpanda avatar step-security-bot avatar steverep avatar tatsuhiro-t avatar tniessen avatar trott avatar uzlopak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

llhttp's Issues

How to get start?

I was looking for llhttp.h file on your release but none found. So, is there any documentation on how would one use your lib?

HPE_INVALID_METHOD possible causing reason?

I encountered some HPE_INVALID_METHOD errors while parsing http protocol(llhttp release branch c api). However, the methods are just normal "GET" "POST". There are spaces(\x20) between http methods and urls.

I tried and got the err positions, but they all seems far away from the request method. Some are in the user-agent, some are in the host

I know nothing about TypeScript, I just searched for "INVALID_METHOD" and found the only possible reason would be no space before url. But in the c code(llhttp.c), there're lots of goto pointing to the "Invalid method" piece of code.

Could u guys help figuring it out?

running tests causing clang to abort on double free

What version of clang should be used to run the tests?

With x64, ubuntu 19.10, clang 11, I get:

free(): double free detected in tcache 2

core/llhttp (master u=) % git clean -x -d
Removing build/
Removing lib/
Removing node_modules/
Removing tags
Removing test/tmp/
core/llhttp (master u=) % git r
Already up to date.
Current branch master is up to date.
core/llhttp (master u=) % npm i

> [email protected] prepare /home/sam/w/core/llhttp
> npm run clean && npm run build-ts


> [email protected] clean /home/sam/w/core/llhttp
> rm -rf lib && rm -rf test/tmp


> [email protected] build-ts /home/sam/w/core/llhttp
> tsc

added 130 packages from 555 contributors and audited 208 packages in 17.015s

2 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

core/llhttp (master u=) % npm test

> [email protected] test /home/sam/w/core/llhttp
> npm run mocha && npm run lint


> [email protected] mocha /home/sam/w/core/llhttp
> mocha --timeout=10000 -r ts-node/register/type-check --reporter progress test/*-test.ts

warning: overriding the module target triple with x86_64-pc-linux-gnu [-Woverride-module]
free(): double free detected in tcache 2
Stack dump:
0.      Program arguments: /usr/bin/clang -g3 -Os -fvisibility=hidden -I /home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/native -include /home/sam/w/core/llhttp/test/tmp/http-loose-none.h /home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/native/fixture.c -msse4.2 -DLLHTTP__TEST -DLLPARSE__ERROR_PAUSE=21 -include /home/sam/w/core/llhttp/test/tmp/cheaders.h /home/sam/w/core/llhttp/test/fixtures/extra.c -DLLHTTP__TEST_HTTP /home/sam/w/core/llhttp/src/native/http.c /home/sam/w/core/llhttp/test/tmp/http-loose-none.bc -o /home/sam/w/core/llhttp/test/tmp/http-loose-none.8804518cbabe475878a3a8a57706e387e22950ed3e9aa6a304e101c771063799
1.      Per-module optimization passes
2.      Running pass 'Dead Argument Elimination' on module '/home/sam/w/core/llhttp/test/tmp/http-loose-none.bc'.
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x1f)[0x7fb8ade7c10f]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm3sys17RunSignalHandlersEv+0x50)[0x7fb8ade7a3c0]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm3sys15CleanupOnSignalEm+0xdd)[0x7fb8ade7b85d]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(+0x8f0c00)[0x7fb8addd0c00]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x15540)[0x7fb8ad4d2540]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xcb)[0x7fb8aa8093eb]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x12b)[0x7fb8aa7e8899]
/lib/x86_64-linux-gnu/libc.so.6(+0x9038e)[0x7fb8aa85338e]
/lib/x86_64-linux-gnu/libc.so.6(+0x984dc)[0x7fb8aa85b4dc]
/lib/x86_64-linux-gnu/libc.so.6(+0x9a13d)[0x7fb8aa85d13d]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm16ValueSymbolTableD2Ev+0x40)[0x7fb8adfca980]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm8FunctionD1Ev+0x9a)[0x7fb8adf4f19a]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm8Function15eraseFromParentEv+0x58)[0x7fb8adf4bb48]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm27DeadArgumentEliminationPass27RemoveDeadStuffFromFunctionEPNS_8FunctionE+0x18bf)[0x7fb8aea7c5cf]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm27DeadArgumentEliminationPass3runERNS_6ModuleERNS_15AnalysisManagerIS1_JEEE+0xca)[0x7fb8aea7c88a]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(+0x159cba7)[0x7fb8aea7cba7]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm6legacy15PassManagerImpl3runERNS_6ModuleE+0x3e0)[0x7fb8adf84820]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang17EmitBackendOutputERNS_17DiagnosticsEngineERKNS_19HeaderSearchOptionsERKNS_14CodeGenOptionsERKNS_13TargetOptionsERKNS_11LangOptionsERKN4llvm10DataLayoutEPNSE_6ModuleENS_13BackendActionESt10unique_ptrINSE_17raw_pwrite_streamESt14default_deleteISM_EE+0x31d5)[0x7fb8ac092215]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang13CodeGenAction13ExecuteActionEv+0x5fb)[0x7fb8ac31e84b]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang14FrontendAction7ExecuteEv+0x48)[0x7fb8ac986518]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang16CompilerInstance13ExecuteActionERNS_14FrontendActionE+0x661)[0x7fb8ac93e041]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang25ExecuteCompilerInvocationEPNS_16CompilerInstanceE+0x66f)[0x7fb8ac9ea95f]
/usr/bin/clang(_Z8cc1_mainN4llvm8ArrayRefIPKcEES2_Pv+0x989)[0x412179]
/usr/bin/clang[0x410491]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(+0x1980e02)[0x7fb8ac68de02]
/usr/lib/x86_64-linux-gnu/libLLVM-11.so.1(_ZN4llvm20CrashRecoveryContext9RunSafelyENS_12function_refIFvvEEE+0xd7)[0x7fb8addd0a97]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZNK5clang6driver10CC1Command7ExecuteEN4llvm8ArrayRefINS2_8OptionalINS2_9StringRefEEEEEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPb+0x119)[0x7fb8ac68d339]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZNK5clang6driver11Compilation14ExecuteCommandERKNS0_7CommandERPS3_+0x2df)[0x7fb8ac665e4f]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZNK5clang6driver11Compilation11ExecuteJobsERKNS0_7JobListERN4llvm15SmallVectorImplISt4pairIiPKNS0_7CommandEEEE+0x7a)[0x7fb8ac665ffa]
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11(_ZN5clang6driver6Driver18ExecuteCompilationERNS0_11CompilationERN4llvm15SmallVectorImplISt4pairIiPKNS0_7CommandEEEE+0xdc)[0x7fb8ac678eec]
/usr/bin/clang(main+0x2382)[0x40fd42]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7fb8aa7ea1e3]
/usr/bin/clang(_start+0x2e)[0x40d6fe]
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 11.0.0-++20200207083130+84e5760a163-1~exp1~20200207074603.102
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
clang: note: diagnostic msg: PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
clang: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/fixture-696a01.c
clang: note: diagnostic msg: /tmp/extra-4ab7b2.c
clang: note: diagnostic msg: /tmp/http-57cdd9.c
clang: note: diagnostic msg: /tmp/fixture-696a01.sh
clang: note: diagnostic msg:

********************
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

/home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/fixture.ts:233
      throw new Error('clang exit code: ' + (ret.status || ret.signal) +
            ^
Error: clang exit code: SIGABRT
arguments: "-g3" "-Os" "-fvisibility=hidden" "-I" "/home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/native" "-include" "/home/sam/w/core/llhttp/test/tmp/http-loose-none.h" "/home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/native/fixture.c" "-msse4.2" "-DLLHTTP__TEST" "-DLLPARSE__ERROR_PAUSE=21" "-include" "/home/sam/w/core/llhttp/test/tmp/cheaders.h" "/home/sam/w/core/llhttp/test/fixtures/extra.c" "-DLLHTTP__TEST_HTTP" "/home/sam/w/core/llhttp/src/native/http.c" "/home/sam/w/core/llhttp/test/tmp/http-loose-none.bc" "-o" "/home/sam/w/core/llhttp/test/tmp/http-loose-none.8804518cbabe475878a3a8a57706e387e22950ed3e9aa6a304e101c771063799"
    at Fixture.clang (/home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/fixture.ts:233:13)
    at Fixture.build (/home/sam/w/core/llhttp/node_modules/llparse-test-fixture/src/fixture.ts:166:12)
    at Object.build (/home/sam/w/core/llhttp/test/fixtures/index.ts:73:19)
    at buildMode (/home/sam/w/core/llhttp/test/md-test.ts:67:10)
    at Object.<anonymous> (/home/sam/w/core/llhttp/test/md-test.ts:78:13)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module.m._compile (/home/sam/w/core/llhttp/node_modules/ts-node/src/index.ts:439:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed> [as .ts] (/home/sam/w/core/llhttp/node_modules/ts-node/src/index.ts:442:12)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at /home/sam/w/core/llhttp/node_modules/mocha/lib/mocha.js:250:27
    at Array.forEach (<anonymous>)
    at Mocha.loadFiles (/home/sam/w/core/llhttp/node_modules/mocha/lib/mocha.js:247:14)
    at Mocha.run (/home/sam/w/core/llhttp/node_modules/mocha/lib/mocha.js:576:10)
    at Object.<anonymous> (/home/sam/w/core/llhttp/node_modules/mocha/bin/_mocha:637:18)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1043:10)
    at internal/main/run_main_module.js:17:11
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] mocha: `mocha --timeout=10000 -r ts-node/register/type-check --reporter progress test/*-test.ts`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] mocha script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/sam/.npm/_logs/2020-02-11T18_19_10_563Z-debug.log
npm ERR! Test failed.  See above for more details.
core/llhttp (master u=) %

Unexpected UNEXPECTED_CONTENT_LENGTH error with lenient parsing

Current behavior: If both Content-Length and Transfer-Encoding: chunked are set on a response, an UNEXPECTED_CONTENT_LENGTH error is thrown, regardless of if llhttp is operating in lenient mode or not.

Expected behavior: If both Content-Length and Transfer-Encoding: chunked are set on a response, an UNEXPECTED_CONTENT_LENGTH error is thrown, but only if llhttp is NOT operating in lenient mode.

Relevant comment:

llhttp/src/llhttp/http.ts

Lines 576 to 590 in e5c3017

/* Present `Transfer-Encoding` header overrides `Content-Length` even if the
* actual coding is not `chunked`. As per spec:
*
* https://www.rfc-editor.org/rfc/rfc7230.html#section-3.3.3
*
* If a message is received with both a Transfer-Encoding and a
* Content-Length header field, the Transfer-Encoding overrides the
* Content-Length. Such a message might indicate an attempt to
* perform request smuggling (Section 9.5) or response splitting
* (Section 9.4) and **ought to be handled as an error**. A sender MUST
* remove the received Content-Length field prior to forwarding such
* a message downstream.
*
* (Note our emphasis on **ought to be handled as an error**
*/

Based on this comment, the purpose of this error seems to be for security - to prevent request smuggling/response splitting. Node.js's name for the lenient flag is insecureHTTPParser, and to my mind, that means that the lenient flag should (insecurely) disable the UNEXPECTED_CONTENT_LENGTH error entirely. However, it does not seem to.

Test code (Node 12.15.0):

http.createServer((req, res) => {
	res.setHeader('content-length', '0')
	res.setHeader('transfer-encoding', 'chunked')
	res.end()
}).listen(12345, () => {
	// expected: request succeeded
	// actual: Parse Error: Content-Length can't be present with chunked encoding
	http.request('http://localhost:12345', { insecureHTTPParser: true })
	.on('error', (err) => console.error(err.message))
	.on('response', () => console.log('request succeeded'))
	.end()
})

I'm proposing that, when in lenient mode, Transfer-Encoding: chunked should be allowed to co-exist with Content-Length, with Content-Length getting ignored. Does that make sense to the project maintainers? If so, I'll open up a PR.

HTTP 1.1 pipeline

Can llhttp support pipeline?
I can't find the instructions for this.
And how do I know how many bytes are being processed when I call llhttp_execute.

Add function to get HTTP method in string

http-parser has http_method_str which returns HTTP method in string.
It would be nice to add the similar function to llhttp. I think the following code would work:

const char* llhttp_method_name(llhttp_method_t m) {
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
  switch (m) {
    HTTP_METHOD_MAP(HTTP_METHOD_GEN)
    default: abort();
  }
#undef HTTP_METHOD_GEN
}

or define string array just like http-parser.

Build shared llhttp

Provided that node can be build with --shared-http-parser and the latter means shared llhttp, it must be possible to build shared libllhttp.so. Calling make install within llhttp`s source tree installs only static libraries.

Distribute "ready-to-use" releases with generated C code

Even though there is a make release target that generates C code and provides release directory:

$ tree release/
release/
├── common.gypi
├── include
│   └── llhttp.h
├── LICENSE-MIT
├── llhttp.gyp
├── README.md
└── src
    ├── api.c
    ├── http.c
    └── llhttp.c

the releases distributed on GitHub are auto-generated from the tags and include only source code.

Would you consider distributing "ready-to-use" releases with generated C code to avoid extra build-time dependencies on consumers of your library? Thanks!

Incorrect handling of folded header values?

In one of the existing llhttp tests (shown at the bottom), it shows llhttp reporting some of the folded whitespace characters as being part of the header value. According to RFC 7230 that shouldn't be the case as we have this ABNF:

 header-field   = field-name ":" OWS field-value OWS

 field-name     = token
 field-value    = *( field-content / obs-fold )
 field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
 field-vchar    = VCHAR / obs-text

 obs-fold       = CRLF 1*( SP / HTAB )
                ; obsolete line folding
                ; see Section 3.2.4

So in this particular test, the header value for the Line1 header should be more like

abcdefghijklmno qrs

instead of

abc\tdef ghi\t\tjkl  mno \t \tqrs

(although the space between o and q shouldn't technically be permitted according to the ABNF, but that's a separate matter).

Do we know if anyone is relying on the current behavior?


Line folding in header value with LF

GET / HTTP/1.1\n\
Line1:   abc\n\
\tdef\n\
 ghi\n\
\t\tjkl\n\
  mno \n\
\t \tqrs\n\
Line2: \t line2\t\n\
Line3:\n\
 line3\n\
Line4: \n\
 \n\
Connection:\n\
 close\n\
\n
off=0 message begin
off=4 len=1 span[url]="/"
off=15 len=5 span[header_field]="Line1"
off=24 len=3 span[header_value]="abc"
off=28 len=4 span[header_value]="\tdef"
off=33 len=4 span[header_value]=" ghi"
off=38 len=5 span[header_value]="\t\tjkl"
off=44 len=6 span[header_value]="  mno "
off=51 len=6 span[header_value]="\t \tqrs"
off=58 len=5 span[header_field]="Line2"
off=67 len=6 span[header_value]="line2\t"
off=74 len=5 span[header_field]="Line3"
off=82 len=5 span[header_value]="line3"
off=88 len=5 span[header_field]="Line4"
off=98 len=0 span[header_value]=""
off=98 len=10 span[header_field]="Connection"
off=111 len=5 span[header_value]="close"
off=118 headers complete method=1 v=1/1 flags=2 content_length=0
off=118 message complete

Additional callbacks

It would be nice to have callbacks after major/minor are set, after header field name is complete, and after header value is complete even if there are more headers. Right now, it's easy enough to emulate, e.g. building up a header field and then on the first header value call recognizing that the field name is complete. However, I'm interested in..

  1. building up a URL, possibly 1 character at a time,
  2. once the URL is complete, selecting a predefined list of headers I'm interested in,
  3. figuring out if the current header name, possibly 1 character at a time, is in this set, &
  4. if so, building up it's value, also 1 character at a time; or if not, ignoring the value.

Adding these callbacks would simplify things, e.g. by pulling header field name logic out of the header value callback, &c. This Issue is a pin, since I'm thinking about how to implement this myself. However, I wanted to get feedback on the idea before I started.

Q: How to import the bindings in Node.js?

Hi @indutny,

It used to be possible to import the old HTTP parser by loading the bindings in Node.js.
I looked into llhttp and the parser generator project but couldn't find an immediate way to do this.
Would you have an example snippet that would let you run the HTTP parser manually in Node.js?
Something similar to: https://stackoverflow.com/a/30180574

Thank you a lot in advance!

Custom / non-standard methods and request/response lines

Thanks for refreshing the parser, it was really a hard-to-extend project. Now it is more modifiable, how about adding some flexibility? Would be very handy to use this parser for custom HTTP-like protocols that utilize different request/response lines but seem similar in other aspects. F.ex., RTSP. If the parser would allow such inputs when it has, say, property customAllowed == true, it'd be very useful and would simplify handling these protocols a lot

CVE-2020-8287 not fixed for 2.X series

Me again. #88 is addressed in the latest releases, but this still prevents us from having a llhttp with the CVE fixed available that is on-par with the current LTS series of node;

Can there be a 2.X release that also includes the fix for this vulnerability? Thanks in advance

llhttp-v3.0.0 lost on_header_field_complete event

These is my code (VC 2010)

When I run this program, 'Content-Length' and 'Connection' header does NOT trigger on_header_field_complete event.
(PS: 'Content-Type' and 'User-Agent' header does trigger on_header_field_complete event )

LPCSTR TEST_RESP = "HTTP/1.1 200 HP Http Server OK\r\n"
		   "Content-Type: text/plain\r\n"
		   "Content-Length: 20\r\n"
		   "User-Agent: IE9\r\n"
		   "Connection: keep-alive\r\n"
		   "\r\n"
		   "[test datas: XXXXXX]";

llhttp_t g_parser;
llhttp_settings_t g_settings;

void TestResp()
{
	size_t len = strlen(TEST_RESP);
	llhttp_errno err = llhttp_execute(&g_parser, TEST_RESP, len);

	if(err == HPE_OK)
	{
		err = llhttp_finish(&g_parser);
	}
}

void InitParser()
{
	llhttp_settings_init(&g_settings);

	g_settings.on_message_begin		= on_message_begin;
	g_settings.on_url			= on_url;
	g_settings.on_url_complete		= on_url_complete;
	g_settings.on_status			= on_status;
	g_settings.on_status_complete		= on_status_complete;
	g_settings.on_header_field		= on_header_field;
	g_settings.on_header_field_complete	= on_header_field_complete;
	g_settings.on_header_value		= on_header_value;
	g_settings.on_header_value_complete	= on_header_value_complete;
	g_settings.on_headers_complete		= on_headers_complete;
	g_settings.on_body			= on_body;
	g_settings.on_message_complete		= on_message_complete;
	g_settings.on_chunk_header		= on_chunk_header;
	g_settings.on_chunk_complete		= on_chunk_complete;

	llhttp_init(&g_parser, HTTP_BOTH, &g_settings);
}

int _tmain(int argc, _TCHAR* argv[])
{
	InitParser();
	TestResp();

	return 0;
}

Any plan to add URL parser?

Do you have any plan to add URL parser to llhttp?
http-parser kindly includes URL parser which is very convenient.
Currently llhttp lacks this functionality. I can use URL parser from http-parser, but some macro names conflict, so I have to provide a header file to declare URL parser struct and functions only.

Linux issue with the SheBang in bin/generate.ts

I'm running make release to generate the c source code to use in a project. I'm working in Linux and I have to tweak the shebang in bin/generate.ts.

Environment

  • Debian 10.2 (Docker Container debian:10-slim)
  • llhttp-2.0.1

What happens?

$ make
./bin/generate.ts
/usr/bin/env: 'npx ts-node': No such file or directory
/usr/bin/env: use -[v]S to pass options in shebang lines
make: *** [Makefile:57: generate] Error 127

Workaround for Linux

$ sed -i 's/env npx/env -S npx/' bin/generate.ts
$ make
./bin/generate.ts
...

Thanks for the great tool!

Pointers on how to build

Hi,
I'm trying to make python bindings of llhttp. I had a couple of attemps writing the minimum required to get it to execute parsing without calling any callback. Got two implementation, one using C++ and pybind11 and the other in plain C. In both cases I dropped the generated files from the last commit into my project and tried to build. Interestingly enough, when comparing to httptools (a python binding for http_parser) without any callback involved, httptools is faster than my binding. In the begining I thought it was pybind11 introducing unneeded overhead, but I'm starting to think it's something to do with compilation flags or #define. Could you provide any indication on how to compile llhttp?

Unused llparse_blobs in llhttp.c causing compilation errors

When this repo is built, the generated llhttp.c file contains unused llparse_blobs; at present llparse_blob1[], llparse_blob7[], llparse_blob9[], and llparse_blob10[] are unused.

This causes compilation failures in Electron.js, since we do not allow unused variables. I'm happy to open a PR to address this myself if i can be pointed in the right direction!

cc @indutny

wasm build?

Starting to looking into using llhttp as a wasm binary instead of https://www.npmjs.com/package/http-parser-js for a http client library.

Anyone got any experience or advice on how one would go about this in the best way? I suppose doing a emcc build from the C files is a start?

Bindings to other languages

I'm curious if this project is open to contribution work for adding bindings to other languages, i.e. Python and Ruby. It'd be pretty cool for packages across these languages, including the existing npm package, to share the same core parsing code.

chunked transfer-encoding terminates without last-chunk

llhttp terminates chunked encoding without last-chunk ('0' + '\r\n').

For example, if I send the following request:

PUT / HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n1\r\nx\r\n\r\n\r\n

llhttp reports that request body completes.
According to RFC 7230 1, chunked encoding requires last-chunk.

add some http request methods support

Check the request methods supported by the http1 module.

console.log(http.METHODS);
[
  "ACL",
  "BIND",
  "CHECKOUT",
  "CONNECT",
  "COPY",
  "DELETE",
  "GET",
  "HEAD",
  "LINK",
  "LOCK",
  "M-SEARCH",
  "MERGE",
  "MKACTIVITY",
  "MKCALENDAR",
  "MKCOL",
  "MOVE",
  "NOTIFY",
  "OPTIONS",
  "PATCH",
  "POST",
  "PROPFIND",
  "PROPPATCH",
  "PURGE",
  "PUT",
  "REBIND",
  "REPORT",
  "SEARCH",
  "SOURCE",
  "SUBSCRIBE",
  "TRACE",
  "UNBIND",
  "UNLINK",
  "UNLOCK",
  "UNSUBSCRIBE"
]

The HTTP1 module does not support the following request methods.

[
  "BASELINE-CONTROL",
  "CHECKIN",
  "LABEL",
  "MKREDIRECTREF",
  "MKWORKSPACE",
  "ORDERPATCH",
  "PRI",
  "UNCHECKOUT",
  "UPDATE",
  "UPDATEREDIRECTREF",
  "VERSION-CONTROL"
]

nodejs/node#33699

relocation R_X86_64_32S against `.rodata.str1.1' can not be used when making a PIE object;

I git cloned your repo to /home dir on Ubuntu 18 LTS then I ran npm install && npm run build && make all && make install after that I tried to compile my program with g++ as follows,

g++ main.cpp -o mainApp -std=c++17 -pthread -lllhttp

The compilation fails with below error,

/usr/bin/ld: /usr/local/lib/libllhttp.a(api.o): relocation R_X86_64_32S against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: /usr/local/lib/libllhttp.a(llhttp.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE
collect2: error: ld returned 1 exit status

Performance requests

Would be nice if:

  • A flag that would cause llhttp to automatically lowercase response headers, so that higher level libraries do not need to perform an additional iteration over headers.

  • Parse and include "keep-alive: timeout (\d+)s" in kOnMessageHeadersComplete, e.g. by changing the type of shouldKeepAlive to an integer, so that higher level libraries do not need to perform an additional iteration over headers.

Refs: https://github.com/mcollina/undici/pull/337/files#diff-50cfa59973c04321b5da0c6da0fdf4feR542-R566

HTTP/2 connection preface

I've found a forgotten feature from old c http parser.

Please see HTTP method registry. PRI is a valid method. RFC 7540 defines the following:

11.6.  PRI Method Registration

   This section registers the "PRI" method in the "HTTP Method Registry"
   ([RFC7231], Section 8.1).

   Method Name:  PRI

   Safe:  Yes

   Idempotent:  Yes

   Specification document(s):  Section 3.5 of this document

   Related information:  This method is never used by an actual client.
      This method will appear to be used when an HTTP/1.1 server or
      intermediary attempts to parse an HTTP/2 connection preface.

HTTP 1.1 parser should not panic when he see HTTP/2 connection preface. It should provide reasonable result for user: everything is fine but we need to switch to HTTP/2 parser.

missing file bin/build.ts ?

Hi,

The npm command npm run build run the following command: ts-node bin/build.ts. But the file build.ts doesn't exist. I guess the command is now ts-node bin/generate.ts ?

If this is the case, i would be happy to pull-request :)

Best Regards,
Thomas

HTTP2(h2) upgrade is not recognized by parser.

Hello again,
The parser correctly recognizes h2c upgrade method from HTTP1.1, however the upgrade for h2 (within TLS) aka
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n
Does not work returning HPE_INVALID_METHOD.
Can you please add it?
Thanks!

Persistence of User Data

I'd like to know whether the parser instance's user data get persists around every call back or not.

Is there existing any method to parsing both request and response at once? v2.2.0

I saw that '/* Initialize the parser in HTTP_BOTH mode, meaning that it will select between

  • HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
  • input.
    */' in README.md,
    But if I parse both request and response in onece llhttp_execute call(the http message like this 'GET / HTTP1.1\r\n\r\nHTTP/1.1 200 OK'), llhttp parse will return an error '6: HPE_INVALID_METHOD' when It prepare to parse the http response message 'HTTP/1.1 200 OK', I guss llhttp think that 'HTTP/1.1 200 OK' also is request message, so the '6: HPE_INVALID_METHOD' error is returned.

Is there existing any method to parsing both request and response at once?

llhttp version: v2.2.0

Content-Length Mismatch

Not sure if this should fall into the responsibility of llhttp but it might make sense to error if the parsed body does not match the content-length header, if such was provided.

Also a question, does llhttp permit body on requests without content-length nor transfer-encoding? If so, how does it determine end of message? Trailing CRLF?

How to access HTTP fields like User-Agent?

I'm trying to figure out this but fails to see any information regards accessing such fields.
I know there is a buffer called Data but am not sure what it supposed to do.

I was only able to access basic fields like Content-Length etc

Build without requiring typescript

As a packager, it would be nice to be able to remove typescript as a build-time dependency of this package, considering that one might want to bootstrap node from source without requiring an existing node environment.

Are there any plans to remove the ad hoc code generation parts using TypeScript?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.