1# llhttp 2[](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