README.md
1# llhttp
2
3Port of [http_parser][0] to [llparse][1].
4
5## Why?
6
7Let's face it, [http_parser][0] is practically unmaintainable. Even
8introduction of a single new method results in a significant code churn.
9
10This project aims to:
11
12* Make it maintainable
13* Verifiable
14* Improving benchmarks where possible
15
16More details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY)
17
18## How?
19
20Over time, different approaches for improving [http_parser][0]'s code base
21were tried. However, all of them failed due to resulting significant performance
22degradation.
23
24This project is a port of [http_parser][0] to TypeScript. [llparse][1] is used
25to generate the output C source file, which could be compiled and
26linked with the embedder's program (like [Node.js][7]).
27
28## Performance
29
30So far llhttp outperforms http_parser:
31
32| | input size | bandwidth | reqs/sec | time |
33|:----------------|-----------:|-------------:|-----------:|--------:|
34| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 ops/sec | 4.61 s |
35| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s |
36
37llhttp is faster by approximately **156%**.
38
39## Maintenance
40
41llhttp project has about 1400 lines of TypeScript code describing the parser
42itself and around 450 lines of C code and headers providing the helper methods.
43The whole [http_parser][0] is implemented in approximately 2500 lines of C, and
44436 lines of headers.
45
46All optimizations and multi-character matching in llhttp are generated
47automatically, and thus doesn't add any extra maintenance cost. On the contrary,
48most of http_parser's code is hand-optimized and unrolled. Instead describing
49"how" it should parse the HTTP requests/responses, a maintainer should
50implement the new features in [http_parser][0] cautiously, considering
51possible performance degradation and manually optimizing the new code.
52
53## Verification
54
55The state machine graph is encoded explicitly in llhttp. The [llparse][1]
56automatically checks the graph for absence of loops and correct reporting of the
57input ranges (spans) like header names and values. In the future, additional
58checks could be performed to get even stricter verification of the llhttp.
59
60## Usage
61
62```C
63#include "llhttp.h"
64
65llhttp_t parser;
66llhttp_settings_t settings;
67
68/* Initialize user callbacks and settings */
69llhttp_settings_init(&settings);
70
71/* Set user callback */
72settings.on_message_complete = handle_on_message_complete;
73
74/* Initialize the parser in HTTP_BOTH mode, meaning that it will select between
75 * HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first
76 * input.
77 */
78llhttp_init(&parser, HTTP_BOTH, &settings);
79
80/* Parse request! */
81const char* request = "GET / HTTP/1.1\r\n\r\n";
82int request_len = strlen(request);
83
84enum llhttp_errno err = llhttp_execute(&parser, request, request_len);
85if (err == HPE_OK) {
86 /* Successfully parsed! */
87} else {
88 fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err),
89 parser.reason);
90}
91```
92
93---
94
95#### LICENSE
96
97This software is licensed under the MIT License.
98
99Copyright Fedor Indutny, 2018.
100
101Permission is hereby granted, free of charge, to any person obtaining a
102copy of this software and associated documentation files (the
103"Software"), to deal in the Software without restriction, including
104without limitation the rights to use, copy, modify, merge, publish,
105distribute, sublicense, and/or sell copies of the Software, and to permit
106persons to whom the Software is furnished to do so, subject to the
107following conditions:
108
109The above copyright notice and this permission notice shall be included
110in all copies or substantial portions of the Software.
111
112THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
113OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
114MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
115NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
116DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
117OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
118USE OR OTHER DEALINGS IN THE SOFTWARE.
119
120[0]: https://github.com/nodejs/http-parser
121[1]: https://github.com/nodejs/llparse
122[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling
123[3]: https://en.wikipedia.org/wiki/Tail_call
124[4]: https://llvm.org/docs/LangRef.html
125[5]: https://llvm.org/docs/LangRef.html#call-instruction
126[6]: https://clang.llvm.org/
127[7]: https://github.com/nodejs/node
128