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