Skip to content

Commit dc12ab9

Browse files
committed
release: 7.0.0
1 parent e1919d4 commit dc12ab9

6 files changed

Lines changed: 6823 additions & 1634 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.5.1)
22
cmake_policy(SET CMP0069 NEW)
33

4-
project(llhttp VERSION 6.0.10)
4+
project(llhttp VERSION 7.0.0)
55
include(GNUInstallDirs)
66

77
set(CMAKE_C_STANDARD 99)

README.md

Lines changed: 292 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# llhttp
2+
[![CI](https://github.com/nodejs/llhttp/workflows/CI/badge.svg)](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI)
23

34
Port of [http_parser][0] to [llparse][1].
45

@@ -22,7 +23,7 @@ were tried. However, all of them failed due to resulting significant performance
2223
degradation.
2324

2425
This project is a port of [http_parser][0] to TypeScript. [llparse][1] is used
25-
to generate the output C and/or bitcode artifacts, which could be compiled and
26+
to generate the output C source file, which could be compiled and
2627
linked with the embedder's program (like [Node.js][7]).
2728

2829
## Performance
@@ -31,7 +32,7 @@ So far llhttp outperforms http_parser:
3132

3233
| | input size | bandwidth | reqs/sec | time |
3334
|:----------------|-----------:|-------------:|-----------:|--------:|
34-
| **llhttp** _(C)_ | 8192.00 mb | 1777.24 mb/s | 3583799.39 ops/sec | 4.61 s |
35+
| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s |
3536
| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s |
3637

3738
llhttp is faster by approximately **156%**.
@@ -89,9 +90,294 @@ if (err == HPE_OK) {
8990
parser.reason);
9091
}
9192
```
93+
For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h).
94+
95+
## API
96+
97+
### llhttp_settings_t
98+
99+
The settings object contains a list of callbacks that the parser will invoke.
100+
101+
The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_PAUSED` (pause the parser):
102+
103+
* `on_message_begin`: Invoked when a new request/response starts.
104+
* `on_message_complete`: Invoked when a request/response has been completedly parsed.
105+
* `on_url_complete`: Invoked after the URL has been parsed.
106+
* `on_method_complete`: Invoked after the HTTP method has been parsed.
107+
* `on_version_complete`: Invoked after the HTTP version has been parsed.
108+
* `on_status_complete`: Invoked after the status code has been parsed.
109+
* `on_header_field_complete`: Invoked after a header name has been parsed.
110+
* `on_header_value_complete`: Invoked after a header value has been parsed.
111+
* `on_chunk_header`: Invoked after a new chunk is started. The current chunk length is stored in `parser->content_length`.
112+
* `on_chunk_extension_name_complete`: Invoked after a chunk extension name is started.
113+
* `on_chunk_extension_value_complete`: Invoked after a chunk extension value is started.
114+
* `on_chunk_complete`: Invoked after a new chunk is received.
115+
* `on_reset`: Invoked after `on_message_complete` and before `on_message_begin` when a new message
116+
is received on the same parser. This is not invoked for the first message of the parser.
117+
118+
The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_USER` (error from the callback):
119+
120+
* `on_url`: Invoked when another character of the URL is received.
121+
* `on_status`: Invoked when another character of the status is received.
122+
* `on_method`: Invoked when another character of the method is received.
123+
When parser is created with `HTTP_BOTH` and the input is a response, this also invoked for the sequence `HTTP/`
124+
of the first message.
125+
* `on_version`: Invoked when another character of the version is received.
126+
* `on_header_field`: Invoked when another character of a header name is received.
127+
* `on_header_value`: Invoked when another character of a header value is received.
128+
* `on_chunk_extension_name`: Invoked when another character of a chunk extension name is received.
129+
* `on_chunk_extension_value`: Invoked when another character of a extension value is received.
130+
131+
The callback `on_headers_complete`, invoked when headers are completed, can return:
132+
133+
* `0`: Proceed normally.
134+
* `1`: Assume that request/response has no body, and proceed to parsing the next message.
135+
* `2`: Assume absence of body (as above) and make `llhttp_execute()` return `HPE_PAUSED_UPGRADE`.
136+
* `-1`: Error
137+
* `HPE_PAUSED`: Pause the parser.
138+
139+
### `void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings)`
140+
141+
Initialize the parser with specific type and user settings.
142+
143+
### `uint8_t llhttp_get_type(llhttp_t* parser)`
144+
145+
Returns the type of the parser.
146+
147+
### `uint8_t llhttp_get_http_major(llhttp_t* parser)`
148+
149+
Returns the major version of the HTTP protocol of the current request/response.
150+
151+
### `uint8_t llhttp_get_http_minor(llhttp_t* parser)`
152+
153+
Returns the minor version of the HTTP protocol of the current request/response.
154+
155+
### `uint8_t llhttp_get_method(llhttp_t* parser)`
156+
157+
Returns the method of the current request.
158+
159+
### `int llhttp_get_status_code(llhttp_t* parser)`
160+
161+
Returns the method of the current response.
162+
163+
### `uint8_t llhttp_get_upgrade(llhttp_t* parser)`
164+
165+
Returns `1` if request includes the `Connection: upgrade` header.
166+
167+
### `void llhttp_reset(llhttp_t* parser)`
168+
169+
Reset an already initialized parser back to the start state, preserving the
170+
existing parser type, callback settings, user data, and lenient flags.
171+
172+
### `void llhttp_settings_init(llhttp_settings_t* settings)`
173+
174+
Initialize the settings object.
175+
176+
### `llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len)`
177+
178+
Parse full or partial request/response, invoking user callbacks along the way.
179+
180+
If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing interrupts,
181+
and such errno is returned from `llhttp_execute()`. If `HPE_PAUSED` was used as a errno,
182+
the execution can be resumed with `llhttp_resume()` call.
183+
184+
In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` is returned
185+
after fully parsing the request/response. If the user wishes to continue parsing,
186+
they need to invoke `llhttp_resume_after_upgrade()`.
187+
188+
**if this function ever returns a non-pause type error, it will continue to return
189+
the same error upon each successive call up until `llhttp_init()` is called.**
190+
191+
### `llhttp_errno_t llhttp_finish(llhttp_t* parser)`
192+
193+
This method should be called when the other side has no further bytes to
194+
send (e.g. shutdown of readable side of the TCP connection.)
195+
196+
Requests without `Content-Length` and other messages might require treating
197+
all incoming bytes as the part of the body, up to the last byte of the
198+
connection.
199+
200+
This method will invoke `on_message_complete()` callback if the
201+
request was terminated safely. Otherwise a error code would be returned.
202+
203+
204+
### `int llhttp_message_needs_eof(const llhttp_t* parser)`
205+
206+
Returns `1` if the incoming message is parsed until the last byte, and has to be completed by calling `llhttp_finish()` on EOF.
207+
208+
### `int llhttp_should_keep_alive(const llhttp_t* parser)`
209+
210+
Returns `1` if there might be any other messages following the last that was
211+
successfully parsed.
212+
213+
### `void llhttp_pause(llhttp_t* parser)`
214+
215+
Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
216+
appropriate error reason.
217+
218+
**Do not call this from user callbacks! User callbacks must return
219+
`HPE_PAUSED` if pausing is required.**
220+
221+
### `void llhttp_resume(llhttp_t* parser)`
222+
223+
Might be called to resume the execution after the pause in user's callback.
224+
225+
See `llhttp_execute()` above for details.
226+
227+
**Call this only if `llhttp_execute()` returns `HPE_PAUSED`.**
228+
229+
### `void llhttp_resume_after_upgrade(llhttp_t* parser)`
230+
231+
Might be called to resume the execution after the pause in user's callback.
232+
See `llhttp_execute()` above for details.
233+
234+
**Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`**
235+
236+
### `llhttp_errno_t llhttp_get_errno(const llhttp_t* parser)`
237+
238+
Returns the latest error.
239+
240+
### `const char* llhttp_get_error_reason(const llhttp_t* parser)`
241+
242+
Returns the verbal explanation of the latest returned error.
243+
244+
**User callback should set error reason when returning the error. See
245+
`llhttp_set_error_reason()` for details.**
246+
247+
### `void llhttp_set_error_reason(llhttp_t* parser, const char* reason)`
248+
249+
Assign verbal description to the returned error. Must be called in user
250+
callbacks right before returning the errno.
251+
252+
**`HPE_USER` error code might be useful in user callbacks.**
253+
254+
### `const char* llhttp_get_error_pos(const llhttp_t* parser)`
255+
256+
Returns the pointer to the last parsed byte before the returned error. The
257+
pointer is relative to the `data` argument of `llhttp_execute()`.
258+
259+
**This method might be useful for counting the number of parsed bytes.**
260+
261+
### `const char* llhttp_errno_name(llhttp_errno_t err)`
262+
263+
Returns textual name of error code.
264+
265+
### `const char* llhttp_method_name(llhttp_method_t method)`
266+
267+
Returns textual name of HTTP method.
268+
269+
### `const char* llhttp_status_name(llhttp_status_t status)`
270+
271+
Returns textual name of HTTP status.
272+
273+
### `void llhttp_set_lenient_headers(llhttp_t* parser, int enabled)`
274+
275+
Enables/disables lenient header value parsing (disabled by default).
276+
Lenient parsing disables header value token checks, extending llhttp's
277+
protocol support to highly non-compliant clients/server.
278+
279+
No `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
280+
lenient parsing is "on".
281+
282+
**USE AT YOUR OWN RISK!**
283+
284+
### `void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled)`
285+
286+
Enables/disables lenient handling of conflicting `Transfer-Encoding` and
287+
`Content-Length` headers (disabled by default).
288+
289+
Normally `llhttp` would error when `Transfer-Encoding` is present in
290+
conjunction with `Content-Length`.
291+
292+
This error is important to prevent HTTP request smuggling, but may be less desirable
293+
for small number of cases involving legacy servers.
294+
295+
**USE AT YOUR OWN RISK!**
296+
297+
### `void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled)`
298+
299+
Enables/disables lenient handling of `Connection: close` and HTTP/1.0
300+
requests responses.
301+
302+
Normally `llhttp` would error on (in strict mode) or discard (in loose mode)
303+
the HTTP request/response after the request/response with `Connection: close`
304+
and `Content-Length`.
305+
306+
This is important to prevent cache poisoning attacks,
307+
but might interact badly with outdated and insecure clients.
308+
309+
With this flag the extra request/response will be parsed normally.
310+
311+
**USE AT YOUR OWN RISK!**
312+
313+
### `void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled)`
314+
315+
Enables/disables lenient handling of `Transfer-Encoding` header.
316+
317+
Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value
318+
and another value after it (either in a single header or in multiple
319+
headers whose value are internally joined using `, `).
320+
321+
This is mandated by the spec to reliably determine request body size and thus
322+
avoid request smuggling.
323+
324+
With this flag the extra value will be parsed normally.
325+
326+
**USE AT YOUR OWN RISK!**
327+
328+
## Build Instructions
329+
330+
Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run:
331+
332+
```sh
333+
npm install
334+
make
335+
```
92336

93337
---
94338

339+
### Bindings to other languages
340+
341+
* Lua: [MunifTanjim/llhttp.lua][11]
342+
* Python: [pallas/pyllhttp][8]
343+
* Ruby: [metabahn/llhttp][9]
344+
* Rust: [JackLiar/rust-llhttp][10]
345+
346+
### Using with CMake
347+
348+
If you want to use this library in a CMake project you can use the snippet below.
349+
350+
```
351+
FetchContent_Declare(llhttp
352+
URL "https://github.com/nodejs/llhttp/archive/refs/tags/v6.0.5.tar.gz") # Using version 6.0.5
353+
354+
FetchContent_MakeAvailable(llhttp)
355+
356+
target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp ${PROJECT_NAME})
357+
```
358+
359+
## Building on Windows
360+
361+
### Installation
362+
363+
* `choco install git`
364+
* `choco install node`
365+
* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer)
366+
* `choco install make` (or if you have MinGW, it comes bundled)
367+
368+
1. Ensure that `Clang` and `make` are in your system path.
369+
2. Using Git Bash, clone the repo to your preferred location.
370+
3. Cd into the cloned directory and run `npm install`
371+
5. Run `make`
372+
6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries.
373+
7. 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`.
374+
375+
### A simple example on linking with the library:
376+
377+
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`.
378+
379+
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`.
380+
95381
#### LICENSE
96382

97383
This software is licensed under the MIT License.
@@ -125,3 +411,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
125411
[5]: https://llvm.org/docs/LangRef.html#call-instruction
126412
[6]: https://clang.llvm.org/
127413
[7]: https://github.com/nodejs/node
414+
[8]: https://github.com/pallas/pyllhttp
415+
[9]: https://github.com/metabahn/llhttp
416+
[10]: https://github.com/JackLiar/rust-llhttp
417+
[11]: https://github.com/MunifTanjim/llhttp.lua

0 commit comments

Comments
 (0)