11cb0ef41Sopenharmony_ci# llhttp
21cb0ef41Sopenharmony_ci[![CI](https://github.com/nodejs/llhttp/workflows/CI/badge.svg)](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI)
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciPort of [http_parser][0] to [llparse][1].
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci## Why?
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciLet's face it, [http_parser][0] is practically unmaintainable. Even
91cb0ef41Sopenharmony_ciintroduction of a single new method results in a significant code churn.
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciThis project aims to:
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci* Make it maintainable
141cb0ef41Sopenharmony_ci* Verifiable
151cb0ef41Sopenharmony_ci* Improving benchmarks where possible
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciMore details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY)
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci## How?
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciOver time, different approaches for improving [http_parser][0]'s code base
221cb0ef41Sopenharmony_ciwere tried. However, all of them failed due to resulting significant performance
231cb0ef41Sopenharmony_cidegradation.
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciThis project is a port of [http_parser][0] to TypeScript. [llparse][1] is used
261cb0ef41Sopenharmony_cito generate the output C source file, which could be compiled and
271cb0ef41Sopenharmony_cilinked with the embedder's program (like [Node.js][7]).
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci## Performance
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciSo far llhttp outperforms http_parser:
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci|                 | input size |  bandwidth   |  reqs/sec  |   time  |
341cb0ef41Sopenharmony_ci|:----------------|-----------:|-------------:|-----------:|--------:|
351cb0ef41Sopenharmony_ci| **llhttp**      | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s |
361cb0ef41Sopenharmony_ci| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s |
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cillhttp is faster by approximately **156%**.
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci## Maintenance
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cillhttp project has about 1400 lines of TypeScript code describing the parser
431cb0ef41Sopenharmony_ciitself and around 450 lines of C code and headers providing the helper methods.
441cb0ef41Sopenharmony_ciThe whole [http_parser][0] is implemented in approximately 2500 lines of C, and
451cb0ef41Sopenharmony_ci436 lines of headers.
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ciAll optimizations and multi-character matching in llhttp are generated
481cb0ef41Sopenharmony_ciautomatically, and thus doesn't add any extra maintenance cost. On the contrary,
491cb0ef41Sopenharmony_cimost of http_parser's code is hand-optimized and unrolled. Instead describing
501cb0ef41Sopenharmony_ci"how" it should parse the HTTP requests/responses, a maintainer should
511cb0ef41Sopenharmony_ciimplement the new features in [http_parser][0] cautiously, considering
521cb0ef41Sopenharmony_cipossible performance degradation and manually optimizing the new code.
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci## Verification
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciThe state machine graph is encoded explicitly in llhttp. The [llparse][1]
571cb0ef41Sopenharmony_ciautomatically checks the graph for absence of loops and correct reporting of the
581cb0ef41Sopenharmony_ciinput ranges (spans) like header names and values. In the future, additional
591cb0ef41Sopenharmony_cichecks could be performed to get even stricter verification of the llhttp.
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci## Usage
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci```C
641cb0ef41Sopenharmony_ci#include "llhttp.h"
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cillhttp_t parser;
671cb0ef41Sopenharmony_cillhttp_settings_t settings;
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci/* Initialize user callbacks and settings */
701cb0ef41Sopenharmony_cillhttp_settings_init(&settings);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci/* Set user callback */
731cb0ef41Sopenharmony_cisettings.on_message_complete = handle_on_message_complete;
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci/* Initialize the parser in HTTP_BOTH mode, meaning that it will select between
761cb0ef41Sopenharmony_ci * HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
771cb0ef41Sopenharmony_ci * input.
781cb0ef41Sopenharmony_ci */
791cb0ef41Sopenharmony_cillhttp_init(&parser, HTTP_BOTH, &settings);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci/* Parse request! */
821cb0ef41Sopenharmony_ciconst char* request = "GET / HTTP/1.1\r\n\r\n";
831cb0ef41Sopenharmony_ciint request_len = strlen(request);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_cienum llhttp_errno err = llhttp_execute(&parser, request, request_len);
861cb0ef41Sopenharmony_ciif (err == HPE_OK) {
871cb0ef41Sopenharmony_ci  /* Successfully parsed! */
881cb0ef41Sopenharmony_ci} else {
891cb0ef41Sopenharmony_ci  fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err),
901cb0ef41Sopenharmony_ci          parser.reason);
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci```
931cb0ef41Sopenharmony_ciFor more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h).
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci## Build Instructions
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ciMake sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run:
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci```sh
1001cb0ef41Sopenharmony_cinpm install
1011cb0ef41Sopenharmony_cimake
1021cb0ef41Sopenharmony_ci```
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci---
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci### Bindings to other languages
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci* Python: [pallas/pyllhttp][8]
1091cb0ef41Sopenharmony_ci* Ruby: [metabahn/llhttp][9]
1101cb0ef41Sopenharmony_ci* Rust: [JackLiar/rust-llhttp][10]
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci### Using with CMake
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciIf you want to use this library in a CMake project you can use the snippet below.
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci```
1171cb0ef41Sopenharmony_ciFetchContent_Declare(llhttp
1181cb0ef41Sopenharmony_ci  URL "https://github.com/nodejs/llhttp/archive/refs/tags/v6.0.5.tar.gz")  # Using version 6.0.5
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ciFetchContent_MakeAvailable(llhttp)
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_citarget_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp ${PROJECT_NAME})
1231cb0ef41Sopenharmony_ci```
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci## Building on Windows
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci### Installation
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci* `choco install git`
1301cb0ef41Sopenharmony_ci* `choco install node`
1311cb0ef41Sopenharmony_ci* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer)
1321cb0ef41Sopenharmony_ci* `choco install make` (or if you have MinGW, it comes bundled)
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci1. Ensure that `Clang` and `make` are in your system path.
1351cb0ef41Sopenharmony_ci2. Using Git Bash, clone the repo to your preferred location.
1361cb0ef41Sopenharmony_ci3. Cd into the cloned directory and run `npm install`
1371cb0ef41Sopenharmony_ci5. Run `make`
1381cb0ef41Sopenharmony_ci6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries.
1391cb0ef41Sopenharmony_ci7. 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`.
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci### A simple example on linking with the library:
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ciAssuming 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`.
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciIf 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`.
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci#### LICENSE
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ciThis software is licensed under the MIT License.
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ciCopyright Fedor Indutny, 2018.
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a
1541cb0ef41Sopenharmony_cicopy of this software and associated documentation files (the
1551cb0ef41Sopenharmony_ci"Software"), to deal in the Software without restriction, including
1561cb0ef41Sopenharmony_ciwithout limitation the rights to use, copy, modify, merge, publish,
1571cb0ef41Sopenharmony_cidistribute, sublicense, and/or sell copies of the Software, and to permit
1581cb0ef41Sopenharmony_cipersons to whom the Software is furnished to do so, subject to the
1591cb0ef41Sopenharmony_cifollowing conditions:
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ciThe above copyright notice and this permission notice shall be included
1621cb0ef41Sopenharmony_ciin all copies or substantial portions of the Software.
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1651cb0ef41Sopenharmony_ciOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1661cb0ef41Sopenharmony_ciMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1671cb0ef41Sopenharmony_ciNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1681cb0ef41Sopenharmony_ciDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1691cb0ef41Sopenharmony_ciOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1701cb0ef41Sopenharmony_ciUSE OR OTHER DEALINGS IN THE SOFTWARE.
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci[0]: https://github.com/nodejs/http-parser
1731cb0ef41Sopenharmony_ci[1]: https://github.com/nodejs/llparse
1741cb0ef41Sopenharmony_ci[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling
1751cb0ef41Sopenharmony_ci[3]: https://en.wikipedia.org/wiki/Tail_call
1761cb0ef41Sopenharmony_ci[4]: https://llvm.org/docs/LangRef.html
1771cb0ef41Sopenharmony_ci[5]: https://llvm.org/docs/LangRef.html#call-instruction
1781cb0ef41Sopenharmony_ci[6]: https://clang.llvm.org/
1791cb0ef41Sopenharmony_ci[7]: https://github.com/nodejs/node
1801cb0ef41Sopenharmony_ci[8]: https://github.com/pallas/pyllhttp
1811cb0ef41Sopenharmony_ci[9]: https://github.com/metabahn/llhttp
1821cb0ef41Sopenharmony_ci[10]: https://github.com/JackLiar/rust-llhttp
183