README.md
1# llhttp
2[![CI](https://github.com/nodejs/llhttp/workflows/CI/badge.svg)](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI)
3
4Port of [http_parser][0] to [llparse][1].
5
6## Why?
7
8Let's face it, [http_parser][0] is practically unmaintainable. Even
9introduction of a single new method results in a significant code churn.
10
11This project aims to:
12
13* Make it maintainable
14* Verifiable
15* Improving benchmarks where possible
16
17More details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY)
18
19## How?
20
21Over time, different approaches for improving [http_parser][0]'s code base
22were tried. However, all of them failed due to resulting significant performance
23degradation.
24
25This project is a port of [http_parser][0] to TypeScript. [llparse][1] is used
26to generate the output C source file, which could be compiled and
27linked with the embedder's program (like [Node.js][7]).
28
29## Performance
30
31So far llhttp outperforms http_parser:
32
33| | input size | bandwidth | reqs/sec | time |
34|:----------------|-----------:|-------------:|-----------:|--------:|
35| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s |
36| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s |
37
38llhttp is faster by approximately **156%**.
39
40## Maintenance
41
42llhttp project has about 1400 lines of TypeScript code describing the parser
43itself and around 450 lines of C code and headers providing the helper methods.
44The whole [http_parser][0] is implemented in approximately 2500 lines of C, and
45436 lines of headers.
46
47All optimizations and multi-character matching in llhttp are generated
48automatically, and thus doesn't add any extra maintenance cost. On the contrary,
49most of http_parser's code is hand-optimized and unrolled. Instead describing
50"how" it should parse the HTTP requests/responses, a maintainer should
51implement the new features in [http_parser][0] cautiously, considering
52possible performance degradation and manually optimizing the new code.
53
54## Verification
55
56The state machine graph is encoded explicitly in llhttp. The [llparse][1]
57automatically checks the graph for absence of loops and correct reporting of the
58input ranges (spans) like header names and values. In the future, additional
59checks could be performed to get even stricter verification of the llhttp.
60
61## Usage
62
63```C
64#include "llhttp.h"
65
66llhttp_t parser;
67llhttp_settings_t settings;
68
69/* Initialize user callbacks and settings */
70llhttp_settings_init(&settings);
71
72/* Set user callback */
73settings.on_message_complete = handle_on_message_complete;
74
75/* Initialize the parser in HTTP_BOTH mode, meaning that it will select between
76 * HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
77 * input.
78 */
79llhttp_init(&parser, HTTP_BOTH, &settings);
80
81/* Parse request! */
82const char* request = "GET / HTTP/1.1\r\n\r\n";
83int request_len = strlen(request);
84
85enum llhttp_errno err = llhttp_execute(&parser, request, request_len);
86if (err == HPE_OK) {
87 /* Successfully parsed! */
88} else {
89 fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err),
90 parser.reason);
91}
92```
93For 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## Build Instructions
96
97Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run:
98
99```sh
100npm install
101make
102```
103
104---
105
106### Bindings to other languages
107
108* Python: [pallas/pyllhttp][8]
109* Ruby: [metabahn/llhttp][9]
110* Rust: [JackLiar/rust-llhttp][10]
111
112### Using with CMake
113
114If you want to use this library in a CMake project you can use the snippet below.
115
116```
117FetchContent_Declare(llhttp
118 URL "https://github.com/nodejs/llhttp/archive/refs/tags/v6.0.5.tar.gz") # Using version 6.0.5
119
120FetchContent_MakeAvailable(llhttp)
121
122target_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp ${PROJECT_NAME})
123```
124
125## Building on Windows
126
127### Installation
128
129* `choco install git`
130* `choco install node`
131* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer)
132* `choco install make` (or if you have MinGW, it comes bundled)
133
1341. Ensure that `Clang` and `make` are in your system path.
1352. Using Git Bash, clone the repo to your preferred location.
1363. Cd into the cloned directory and run `npm install`
1375. Run `make`
1386. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries.
1397. 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`.
140
141### A simple example on linking with the library:
142
143Assuming 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`.
144
145If 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`.
146
147#### LICENSE
148
149This software is licensed under the MIT License.
150
151Copyright Fedor Indutny, 2018.
152
153Permission is hereby granted, free of charge, to any person obtaining a
154copy of this software and associated documentation files (the
155"Software"), to deal in the Software without restriction, including
156without limitation the rights to use, copy, modify, merge, publish,
157distribute, sublicense, and/or sell copies of the Software, and to permit
158persons to whom the Software is furnished to do so, subject to the
159following conditions:
160
161The above copyright notice and this permission notice shall be included
162in all copies or substantial portions of the Software.
163
164THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
165OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
166MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
167NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
168DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
169OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
170USE OR OTHER DEALINGS IN THE SOFTWARE.
171
172[0]: https://github.com/nodejs/http-parser
173[1]: https://github.com/nodejs/llparse
174[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling
175[3]: https://en.wikipedia.org/wiki/Tail_call
176[4]: https://llvm.org/docs/LangRef.html
177[5]: https://llvm.org/docs/LangRef.html#call-instruction
178[6]: https://clang.llvm.org/
179[7]: https://github.com/nodejs/node
180[8]: https://github.com/pallas/pyllhttp
181[9]: https://github.com/metabahn/llhttp
182[10]: https://github.com/JackLiar/rust-llhttp
183