12c593315Sopenharmony_ci# llhttp 22c593315Sopenharmony_ci[](https://github.com/nodejs/llhttp/actions?query=workflow%3ACI) 32c593315Sopenharmony_ci 42c593315Sopenharmony_ciPort of [http_parser][0] to [llparse][1]. 52c593315Sopenharmony_ci 62c593315Sopenharmony_ci## Why? 72c593315Sopenharmony_ci 82c593315Sopenharmony_ciLet's face it, [http_parser][0] is practically unmaintainable. Even 92c593315Sopenharmony_ciintroduction of a single new method results in a significant code churn. 102c593315Sopenharmony_ci 112c593315Sopenharmony_ciThis project aims to: 122c593315Sopenharmony_ci 132c593315Sopenharmony_ci* Make it maintainable 142c593315Sopenharmony_ci* Verifiable 152c593315Sopenharmony_ci* Improving benchmarks where possible 162c593315Sopenharmony_ci 172c593315Sopenharmony_ciMore details in [Fedor Indutny's talk at JSConf EU 2019](https://youtu.be/x3k_5Mi66sY) 182c593315Sopenharmony_ci 192c593315Sopenharmony_ci## How? 202c593315Sopenharmony_ci 212c593315Sopenharmony_ciOver time, different approaches for improving [http_parser][0]'s code base 222c593315Sopenharmony_ciwere tried. However, all of them failed due to resulting significant performance 232c593315Sopenharmony_cidegradation. 242c593315Sopenharmony_ci 252c593315Sopenharmony_ciThis project is a port of [http_parser][0] to TypeScript. [llparse][1] is used 262c593315Sopenharmony_cito generate the output C source file, which could be compiled and 272c593315Sopenharmony_cilinked with the embedder's program (like [Node.js][7]). 282c593315Sopenharmony_ci 292c593315Sopenharmony_ci## Performance 302c593315Sopenharmony_ci 312c593315Sopenharmony_ciSo far llhttp outperforms http_parser: 322c593315Sopenharmony_ci 332c593315Sopenharmony_ci| | input size | bandwidth | reqs/sec | time | 342c593315Sopenharmony_ci|:----------------|-----------:|-------------:|-----------:|--------:| 352c593315Sopenharmony_ci| **llhttp** | 8192.00 mb | 1777.24 mb/s | 3583799.39 req/sec | 4.61 s | 362c593315Sopenharmony_ci| **http_parser** | 8192.00 mb | 694.66 mb/s | 1406180.33 req/sec | 11.79 s | 372c593315Sopenharmony_ci 382c593315Sopenharmony_cillhttp is faster by approximately **156%**. 392c593315Sopenharmony_ci 402c593315Sopenharmony_ci## Maintenance 412c593315Sopenharmony_ci 422c593315Sopenharmony_cillhttp project has about 1400 lines of TypeScript code describing the parser 432c593315Sopenharmony_ciitself and around 450 lines of C code and headers providing the helper methods. 442c593315Sopenharmony_ciThe whole [http_parser][0] is implemented in approximately 2500 lines of C, and 452c593315Sopenharmony_ci436 lines of headers. 462c593315Sopenharmony_ci 472c593315Sopenharmony_ciAll optimizations and multi-character matching in llhttp are generated 482c593315Sopenharmony_ciautomatically, and thus doesn't add any extra maintenance cost. On the contrary, 492c593315Sopenharmony_cimost of http_parser's code is hand-optimized and unrolled. Instead describing 502c593315Sopenharmony_ci"how" it should parse the HTTP requests/responses, a maintainer should 512c593315Sopenharmony_ciimplement the new features in [http_parser][0] cautiously, considering 522c593315Sopenharmony_cipossible performance degradation and manually optimizing the new code. 532c593315Sopenharmony_ci 542c593315Sopenharmony_ci## Verification 552c593315Sopenharmony_ci 562c593315Sopenharmony_ciThe state machine graph is encoded explicitly in llhttp. The [llparse][1] 572c593315Sopenharmony_ciautomatically checks the graph for absence of loops and correct reporting of the 582c593315Sopenharmony_ciinput ranges (spans) like header names and values. In the future, additional 592c593315Sopenharmony_cichecks could be performed to get even stricter verification of the llhttp. 602c593315Sopenharmony_ci 612c593315Sopenharmony_ci## Usage 622c593315Sopenharmony_ci 632c593315Sopenharmony_ci```C 642c593315Sopenharmony_ci#include "stdio.h" 652c593315Sopenharmony_ci#include "llhttp.h" 662c593315Sopenharmony_ci#include "string.h" 672c593315Sopenharmony_ci 682c593315Sopenharmony_ciint handle_on_message_complete(llhttp_t* parser) { 692c593315Sopenharmony_ci fprintf(stdout, "Message completed!\n"); 702c593315Sopenharmony_ci return 0; 712c593315Sopenharmony_ci} 722c593315Sopenharmony_ci 732c593315Sopenharmony_ciint main() { 742c593315Sopenharmony_ci llhttp_t parser; 752c593315Sopenharmony_ci llhttp_settings_t settings; 762c593315Sopenharmony_ci 772c593315Sopenharmony_ci /*Initialize user callbacks and settings */ 782c593315Sopenharmony_ci llhttp_settings_init(&settings); 792c593315Sopenharmony_ci 802c593315Sopenharmony_ci /*Set user callback */ 812c593315Sopenharmony_ci settings.on_message_complete = handle_on_message_complete; 822c593315Sopenharmony_ci 832c593315Sopenharmony_ci /*Initialize the parser in HTTP_BOTH mode, meaning that it will select between 842c593315Sopenharmony_ci *HTTP_REQUEST and HTTP_RESPONSE parsing automatically while reading the first 852c593315Sopenharmony_ci *input. 862c593315Sopenharmony_ci */ 872c593315Sopenharmony_ci llhttp_init(&parser, HTTP_BOTH, &settings); 882c593315Sopenharmony_ci 892c593315Sopenharmony_ci /*Parse request! */ 902c593315Sopenharmony_ci const char* request = "GET / HTTP/1.1\r\n\r\n"; 912c593315Sopenharmony_ci int request_len = strlen(request); 922c593315Sopenharmony_ci 932c593315Sopenharmony_ci enum llhttp_errno err = llhttp_execute(&parser, request, request_len); 942c593315Sopenharmony_ci if (err == HPE_OK) { 952c593315Sopenharmony_ci fprintf(stdout, "Successfully parsed!\n"); 962c593315Sopenharmony_ci } else { 972c593315Sopenharmony_ci fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err), parser.reason); 982c593315Sopenharmony_ci } 992c593315Sopenharmony_ci} 1002c593315Sopenharmony_ci``` 1012c593315Sopenharmony_ciFor more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h). 1022c593315Sopenharmony_ci 1032c593315Sopenharmony_ci## API 1042c593315Sopenharmony_ci 1052c593315Sopenharmony_ci### llhttp_settings_t 1062c593315Sopenharmony_ci 1072c593315Sopenharmony_ciThe settings object contains a list of callbacks that the parser will invoke. 1082c593315Sopenharmony_ci 1092c593315Sopenharmony_ciThe following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_PAUSED` (pause the parser): 1102c593315Sopenharmony_ci 1112c593315Sopenharmony_ci* `on_message_begin`: Invoked when a new request/response starts. 1122c593315Sopenharmony_ci* `on_message_complete`: Invoked when a request/response has been completedly parsed. 1132c593315Sopenharmony_ci* `on_url_complete`: Invoked after the URL has been parsed. 1142c593315Sopenharmony_ci* `on_method_complete`: Invoked after the HTTP method has been parsed. 1152c593315Sopenharmony_ci* `on_version_complete`: Invoked after the HTTP version has been parsed. 1162c593315Sopenharmony_ci* `on_status_complete`: Invoked after the status code has been parsed. 1172c593315Sopenharmony_ci* `on_header_field_complete`: Invoked after a header name has been parsed. 1182c593315Sopenharmony_ci* `on_header_value_complete`: Invoked after a header value has been parsed. 1192c593315Sopenharmony_ci* `on_chunk_header`: Invoked after a new chunk is started. The current chunk length is stored in `parser->content_length`. 1202c593315Sopenharmony_ci* `on_chunk_extension_name_complete`: Invoked after a chunk extension name is started. 1212c593315Sopenharmony_ci* `on_chunk_extension_value_complete`: Invoked after a chunk extension value is started. 1222c593315Sopenharmony_ci* `on_chunk_complete`: Invoked after a new chunk is received. 1232c593315Sopenharmony_ci* `on_reset`: Invoked after `on_message_complete` and before `on_message_begin` when a new message 1242c593315Sopenharmony_ci is received on the same parser. This is not invoked for the first message of the parser. 1252c593315Sopenharmony_ci 1262c593315Sopenharmony_ciThe following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_USER` (error from the callback): 1272c593315Sopenharmony_ci 1282c593315Sopenharmony_ci* `on_url`: Invoked when another character of the URL is received. 1292c593315Sopenharmony_ci* `on_status`: Invoked when another character of the status is received. 1302c593315Sopenharmony_ci* `on_method`: Invoked when another character of the method is received. 1312c593315Sopenharmony_ci When parser is created with `HTTP_BOTH` and the input is a response, this also invoked for the sequence `HTTP/` 1322c593315Sopenharmony_ci of the first message. 1332c593315Sopenharmony_ci* `on_version`: Invoked when another character of the version is received. 1342c593315Sopenharmony_ci* `on_header_field`: Invoked when another character of a header name is received. 1352c593315Sopenharmony_ci* `on_header_value`: Invoked when another character of a header value is received. 1362c593315Sopenharmony_ci* `on_chunk_extension_name`: Invoked when another character of a chunk extension name is received. 1372c593315Sopenharmony_ci* `on_chunk_extension_value`: Invoked when another character of a extension value is received. 1382c593315Sopenharmony_ci 1392c593315Sopenharmony_ciThe callback `on_headers_complete`, invoked when headers are completed, can return: 1402c593315Sopenharmony_ci 1412c593315Sopenharmony_ci* `0`: Proceed normally. 1422c593315Sopenharmony_ci* `1`: Assume that request/response has no body, and proceed to parsing the next message. 1432c593315Sopenharmony_ci* `2`: Assume absence of body (as above) and make `llhttp_execute()` return `HPE_PAUSED_UPGRADE`. 1442c593315Sopenharmony_ci* `-1`: Error 1452c593315Sopenharmony_ci* `HPE_PAUSED`: Pause the parser. 1462c593315Sopenharmony_ci 1472c593315Sopenharmony_ci### `void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings)` 1482c593315Sopenharmony_ci 1492c593315Sopenharmony_ciInitialize the parser with specific type and user settings. 1502c593315Sopenharmony_ci 1512c593315Sopenharmony_ci### `uint8_t llhttp_get_type(llhttp_t* parser)` 1522c593315Sopenharmony_ci 1532c593315Sopenharmony_ciReturns the type of the parser. 1542c593315Sopenharmony_ci 1552c593315Sopenharmony_ci### `uint8_t llhttp_get_http_major(llhttp_t* parser)` 1562c593315Sopenharmony_ci 1572c593315Sopenharmony_ciReturns the major version of the HTTP protocol of the current request/response. 1582c593315Sopenharmony_ci 1592c593315Sopenharmony_ci### `uint8_t llhttp_get_http_minor(llhttp_t* parser)` 1602c593315Sopenharmony_ci 1612c593315Sopenharmony_ciReturns the minor version of the HTTP protocol of the current request/response. 1622c593315Sopenharmony_ci 1632c593315Sopenharmony_ci### `uint8_t llhttp_get_method(llhttp_t* parser)` 1642c593315Sopenharmony_ci 1652c593315Sopenharmony_ciReturns the method of the current request. 1662c593315Sopenharmony_ci 1672c593315Sopenharmony_ci### `int llhttp_get_status_code(llhttp_t* parser)` 1682c593315Sopenharmony_ci 1692c593315Sopenharmony_ciReturns the method of the current response. 1702c593315Sopenharmony_ci 1712c593315Sopenharmony_ci### `uint8_t llhttp_get_upgrade(llhttp_t* parser)` 1722c593315Sopenharmony_ci 1732c593315Sopenharmony_ciReturns `1` if request includes the `Connection: upgrade` header. 1742c593315Sopenharmony_ci 1752c593315Sopenharmony_ci### `void llhttp_reset(llhttp_t* parser)` 1762c593315Sopenharmony_ci 1772c593315Sopenharmony_ciReset an already initialized parser back to the start state, preserving the 1782c593315Sopenharmony_ciexisting parser type, callback settings, user data, and lenient flags. 1792c593315Sopenharmony_ci 1802c593315Sopenharmony_ci### `void llhttp_settings_init(llhttp_settings_t* settings)` 1812c593315Sopenharmony_ci 1822c593315Sopenharmony_ciInitialize the settings object. 1832c593315Sopenharmony_ci 1842c593315Sopenharmony_ci### `llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len)` 1852c593315Sopenharmony_ci 1862c593315Sopenharmony_ciParse full or partial request/response, invoking user callbacks along the way. 1872c593315Sopenharmony_ci 1882c593315Sopenharmony_ciIf any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing interrupts, 1892c593315Sopenharmony_ciand such errno is returned from `llhttp_execute()`. If `HPE_PAUSED` was used as a errno, 1902c593315Sopenharmony_cithe execution can be resumed with `llhttp_resume()` call. 1912c593315Sopenharmony_ci 1922c593315Sopenharmony_ciIn a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` is returned 1932c593315Sopenharmony_ciafter fully parsing the request/response. If the user wishes to continue parsing, 1942c593315Sopenharmony_cithey need to invoke `llhttp_resume_after_upgrade()`. 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_ci**if this function ever returns a non-pause type error, it will continue to return 1972c593315Sopenharmony_cithe same error upon each successive call up until `llhttp_init()` is called.** 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_ci### `llhttp_errno_t llhttp_finish(llhttp_t* parser)` 2002c593315Sopenharmony_ci 2012c593315Sopenharmony_ciThis method should be called when the other side has no further bytes to 2022c593315Sopenharmony_cisend (e.g. shutdown of readable side of the TCP connection.) 2032c593315Sopenharmony_ci 2042c593315Sopenharmony_ciRequests without `Content-Length` and other messages might require treating 2052c593315Sopenharmony_ciall incoming bytes as the part of the body, up to the last byte of the 2062c593315Sopenharmony_ciconnection. 2072c593315Sopenharmony_ci 2082c593315Sopenharmony_ciThis method will invoke `on_message_complete()` callback if the 2092c593315Sopenharmony_cirequest was terminated safely. Otherwise a error code would be returned. 2102c593315Sopenharmony_ci 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_ci### `int llhttp_message_needs_eof(const llhttp_t* parser)` 2132c593315Sopenharmony_ci 2142c593315Sopenharmony_ciReturns `1` if the incoming message is parsed until the last byte, and has to be completed by calling `llhttp_finish()` on EOF. 2152c593315Sopenharmony_ci 2162c593315Sopenharmony_ci### `int llhttp_should_keep_alive(const llhttp_t* parser)` 2172c593315Sopenharmony_ci 2182c593315Sopenharmony_ciReturns `1` if there might be any other messages following the last that was 2192c593315Sopenharmony_cisuccessfully parsed. 2202c593315Sopenharmony_ci 2212c593315Sopenharmony_ci### `void llhttp_pause(llhttp_t* parser)` 2222c593315Sopenharmony_ci 2232c593315Sopenharmony_ciMake further calls of `llhttp_execute()` return `HPE_PAUSED` and set 2242c593315Sopenharmony_ciappropriate error reason. 2252c593315Sopenharmony_ci 2262c593315Sopenharmony_ci**Do not call this from user callbacks! User callbacks must return 2272c593315Sopenharmony_ci`HPE_PAUSED` if pausing is required.** 2282c593315Sopenharmony_ci 2292c593315Sopenharmony_ci### `void llhttp_resume(llhttp_t* parser)` 2302c593315Sopenharmony_ci 2312c593315Sopenharmony_ciMight be called to resume the execution after the pause in user's callback. 2322c593315Sopenharmony_ci 2332c593315Sopenharmony_ciSee `llhttp_execute()` above for details. 2342c593315Sopenharmony_ci 2352c593315Sopenharmony_ci**Call this only if `llhttp_execute()` returns `HPE_PAUSED`.** 2362c593315Sopenharmony_ci 2372c593315Sopenharmony_ci### `void llhttp_resume_after_upgrade(llhttp_t* parser)` 2382c593315Sopenharmony_ci 2392c593315Sopenharmony_ciMight be called to resume the execution after the pause in user's callback. 2402c593315Sopenharmony_ciSee `llhttp_execute()` above for details. 2412c593315Sopenharmony_ci 2422c593315Sopenharmony_ci**Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`** 2432c593315Sopenharmony_ci 2442c593315Sopenharmony_ci### `llhttp_errno_t llhttp_get_errno(const llhttp_t* parser)` 2452c593315Sopenharmony_ci 2462c593315Sopenharmony_ciReturns the latest error. 2472c593315Sopenharmony_ci 2482c593315Sopenharmony_ci### `const char* llhttp_get_error_reason(const llhttp_t* parser)` 2492c593315Sopenharmony_ci 2502c593315Sopenharmony_ciReturns the verbal explanation of the latest returned error. 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_ci**User callback should set error reason when returning the error. See 2532c593315Sopenharmony_ci`llhttp_set_error_reason()` for details.** 2542c593315Sopenharmony_ci 2552c593315Sopenharmony_ci### `void llhttp_set_error_reason(llhttp_t* parser, const char* reason)` 2562c593315Sopenharmony_ci 2572c593315Sopenharmony_ciAssign verbal description to the returned error. Must be called in user 2582c593315Sopenharmony_cicallbacks right before returning the errno. 2592c593315Sopenharmony_ci 2602c593315Sopenharmony_ci**`HPE_USER` error code might be useful in user callbacks.** 2612c593315Sopenharmony_ci 2622c593315Sopenharmony_ci### `const char* llhttp_get_error_pos(const llhttp_t* parser)` 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_ciReturns the pointer to the last parsed byte before the returned error. The 2652c593315Sopenharmony_cipointer is relative to the `data` argument of `llhttp_execute()`. 2662c593315Sopenharmony_ci 2672c593315Sopenharmony_ci**This method might be useful for counting the number of parsed bytes.** 2682c593315Sopenharmony_ci 2692c593315Sopenharmony_ci### `const char* llhttp_errno_name(llhttp_errno_t err)` 2702c593315Sopenharmony_ci 2712c593315Sopenharmony_ciReturns textual name of error code. 2722c593315Sopenharmony_ci 2732c593315Sopenharmony_ci### `const char* llhttp_method_name(llhttp_method_t method)` 2742c593315Sopenharmony_ci 2752c593315Sopenharmony_ciReturns textual name of HTTP method. 2762c593315Sopenharmony_ci 2772c593315Sopenharmony_ci### `const char* llhttp_status_name(llhttp_status_t status)` 2782c593315Sopenharmony_ci 2792c593315Sopenharmony_ciReturns textual name of HTTP status. 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_ci### `void llhttp_set_lenient_headers(llhttp_t* parser, int enabled)` 2822c593315Sopenharmony_ci 2832c593315Sopenharmony_ciEnables/disables lenient header value parsing (disabled by default). 2842c593315Sopenharmony_ciLenient parsing disables header value token checks, extending llhttp's 2852c593315Sopenharmony_ciprotocol support to highly non-compliant clients/server. 2862c593315Sopenharmony_ci 2872c593315Sopenharmony_ciNo `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when 2882c593315Sopenharmony_cilenient parsing is "on". 2892c593315Sopenharmony_ci 2902c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** 2912c593315Sopenharmony_ci 2922c593315Sopenharmony_ci### `void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled)` 2932c593315Sopenharmony_ci 2942c593315Sopenharmony_ciEnables/disables lenient handling of conflicting `Transfer-Encoding` and 2952c593315Sopenharmony_ci`Content-Length` headers (disabled by default). 2962c593315Sopenharmony_ci 2972c593315Sopenharmony_ciNormally `llhttp` would error when `Transfer-Encoding` is present in 2982c593315Sopenharmony_ciconjunction with `Content-Length`. 2992c593315Sopenharmony_ci 3002c593315Sopenharmony_ciThis error is important to prevent HTTP request smuggling, but may be less desirable 3012c593315Sopenharmony_cifor small number of cases involving legacy servers. 3022c593315Sopenharmony_ci 3032c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** 3042c593315Sopenharmony_ci 3052c593315Sopenharmony_ci### `void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled)` 3062c593315Sopenharmony_ci 3072c593315Sopenharmony_ciEnables/disables lenient handling of `Connection: close` and HTTP/1.0 3082c593315Sopenharmony_cirequests responses. 3092c593315Sopenharmony_ci 3102c593315Sopenharmony_ciNormally `llhttp` would error the HTTP request/response 3112c593315Sopenharmony_ciafter the request/response with `Connection: close` and `Content-Length`. 3122c593315Sopenharmony_ci 3132c593315Sopenharmony_ciThis is important to prevent cache poisoning attacks, 3142c593315Sopenharmony_cibut might interact badly with outdated and insecure clients. 3152c593315Sopenharmony_ci 3162c593315Sopenharmony_ciWith this flag the extra request/response will be parsed normally. 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!** 3192c593315Sopenharmony_ci 3202c593315Sopenharmony_ci### `void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled)` 3212c593315Sopenharmony_ci 3222c593315Sopenharmony_ciEnables/disables lenient handling of `Transfer-Encoding` header. 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_ciNormally `llhttp` would error when a `Transfer-Encoding` has `chunked` value 3252c593315Sopenharmony_ciand another value after it (either in a single header or in multiple 3262c593315Sopenharmony_ciheaders whose value are internally joined using `, `). 3272c593315Sopenharmony_ci 3282c593315Sopenharmony_ciThis is mandated by the spec to reliably determine request body size and thus 3292c593315Sopenharmony_ciavoid request smuggling. 3302c593315Sopenharmony_ci 3312c593315Sopenharmony_ciWith this flag the extra value will be parsed normally. 3322c593315Sopenharmony_ci 3332c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** 3342c593315Sopenharmony_ci 3352c593315Sopenharmony_ci### `void llhttp_set_lenient_version(llhttp_t* parser, int enabled)` 3362c593315Sopenharmony_ci 3372c593315Sopenharmony_ciEnables/disables lenient handling of HTTP version. 3382c593315Sopenharmony_ci 3392c593315Sopenharmony_ciNormally `llhttp` would error when the HTTP version in the request or status line 3402c593315Sopenharmony_ciis not `0.9`, `1.0`, `1.1` or `2.0`. 3412c593315Sopenharmony_ciWith this flag the extra value will be parsed normally. 3422c593315Sopenharmony_ci 3432c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will allow unsupported HTTP versions. USE WITH CAUTION!** 3442c593315Sopenharmony_ci 3452c593315Sopenharmony_ci### `void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled)` 3462c593315Sopenharmony_ci 3472c593315Sopenharmony_ciEnables/disables lenient handling of additional data received after a message ends 3482c593315Sopenharmony_ciand keep-alive is disabled. 3492c593315Sopenharmony_ci 3502c593315Sopenharmony_ciNormally `llhttp` would error when additional unexpected data is received if the message 3512c593315Sopenharmony_cicontains the `Connection` header with `close` value. 3522c593315Sopenharmony_ciWith this flag the extra data will discarded without throwing an error. 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to poisoning attacks. USE WITH CAUTION!** 3552c593315Sopenharmony_ci 3562c593315Sopenharmony_ci### `void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled)` 3572c593315Sopenharmony_ci 3582c593315Sopenharmony_ciEnables/disables lenient handling of incomplete CRLF sequences. 3592c593315Sopenharmony_ci 3602c593315Sopenharmony_ciNormally `llhttp` would error when a CR is not followed by LF when terminating the 3612c593315Sopenharmony_cirequest line, the status line, the headers or a chunk header. 3622c593315Sopenharmony_ciWith this flag only a CR is required to terminate such sections. 3632c593315Sopenharmony_ci 3642c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** 3652c593315Sopenharmony_ci 3662c593315Sopenharmony_ci### `void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled)` 3672c593315Sopenharmony_ci 3682c593315Sopenharmony_ciEnables/disables lenient handling of chunks not separated via CRLF. 3692c593315Sopenharmony_ci 3702c593315Sopenharmony_ciNormally `llhttp` would error when after a chunk data a CRLF is missing before 3712c593315Sopenharmony_cistarting a new chunk. 3722c593315Sopenharmony_ciWith this flag the new chunk can start immediately after the previous one. 3732c593315Sopenharmony_ci 3742c593315Sopenharmony_ci**Enabling this flag can pose a security issue since you will be exposed to request smuggling attacks. USE WITH CAUTION!** 3752c593315Sopenharmony_ci 3762c593315Sopenharmony_ci## Build Instructions 3772c593315Sopenharmony_ci 3782c593315Sopenharmony_ciMake sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run: 3792c593315Sopenharmony_ci 3802c593315Sopenharmony_ci```sh 3812c593315Sopenharmony_cinpm install 3822c593315Sopenharmony_cimake 3832c593315Sopenharmony_ci``` 3842c593315Sopenharmony_ci 3852c593315Sopenharmony_ci--- 3862c593315Sopenharmony_ci 3872c593315Sopenharmony_ci### Bindings to other languages 3882c593315Sopenharmony_ci 3892c593315Sopenharmony_ci* Lua: [MunifTanjim/llhttp.lua][11] 3902c593315Sopenharmony_ci* Python: [pallas/pyllhttp][8] 3912c593315Sopenharmony_ci* Ruby: [metabahn/llhttp][9] 3922c593315Sopenharmony_ci* Rust: [JackLiar/rust-llhttp][10] 3932c593315Sopenharmony_ci 3942c593315Sopenharmony_ci### Using with CMake 3952c593315Sopenharmony_ci 3962c593315Sopenharmony_ciIf you want to use this library in a CMake project as a shared library, you can use the snippet below. 3972c593315Sopenharmony_ci 3982c593315Sopenharmony_ci``` 3992c593315Sopenharmony_ciFetchContent_Declare(llhttp 4002c593315Sopenharmony_ci URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz") 4012c593315Sopenharmony_ci 4022c593315Sopenharmony_ciFetchContent_MakeAvailable(llhttp) 4032c593315Sopenharmony_ci 4042c593315Sopenharmony_ci# Link with the llhttp_shared target 4052c593315Sopenharmony_citarget_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_shared ${PROJECT_NAME}) 4062c593315Sopenharmony_ci``` 4072c593315Sopenharmony_ci 4082c593315Sopenharmony_ciIf you want to use this library in a CMake project as a static library, you can set some cache variables first. 4092c593315Sopenharmony_ci 4102c593315Sopenharmony_ci``` 4112c593315Sopenharmony_ciFetchContent_Declare(llhttp 4122c593315Sopenharmony_ci URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v8.1.0.tar.gz") 4132c593315Sopenharmony_ci 4142c593315Sopenharmony_ciset(BUILD_SHARED_LIBS OFF CACHE INTERNAL "") 4152c593315Sopenharmony_ciset(BUILD_STATIC_LIBS ON CACHE INTERNAL "") 4162c593315Sopenharmony_ciFetchContent_MakeAvailable(llhttp) 4172c593315Sopenharmony_ci 4182c593315Sopenharmony_ci# Link with the llhttp_static target 4192c593315Sopenharmony_citarget_link_libraries(${EXAMPLE_PROJECT_NAME} ${PROJECT_LIBRARIES} llhttp_static ${PROJECT_NAME}) 4202c593315Sopenharmony_ci``` 4212c593315Sopenharmony_ci 4222c593315Sopenharmony_ci_Note that using the git repo directly (e.g., via a git repo url and tag) will not work with FetchContent_Declare because [CMakeLists.txt](./CMakeLists.txt) requires string replacements (e.g., `_RELEASE_`) before it will build._ 4232c593315Sopenharmony_ci 4242c593315Sopenharmony_ci## Building on Windows 4252c593315Sopenharmony_ci 4262c593315Sopenharmony_ci### Installation 4272c593315Sopenharmony_ci 4282c593315Sopenharmony_ci* `choco install git` 4292c593315Sopenharmony_ci* `choco install node` 4302c593315Sopenharmony_ci* `choco install llvm` (or install the `C++ Clang tools for Windows` optional package from the Visual Studio 2019 installer) 4312c593315Sopenharmony_ci* `choco install make` (or if you have MinGW, it comes bundled) 4322c593315Sopenharmony_ci 4332c593315Sopenharmony_ci1. Ensure that `Clang` and `make` are in your system path. 4342c593315Sopenharmony_ci2. Using Git Bash, clone the repo to your preferred location. 4352c593315Sopenharmony_ci3. Cd into the cloned directory and run `npm install` 4362c593315Sopenharmony_ci5. Run `make` 4372c593315Sopenharmony_ci6. Your `repo/build` directory should now have `libllhttp.a` and `libllhttp.so` static and dynamic libraries. 4382c593315Sopenharmony_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`. 4392c593315Sopenharmony_ci 4402c593315Sopenharmony_ci### A simple example on linking with the library: 4412c593315Sopenharmony_ci 4422c593315Sopenharmony_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`. 4432c593315Sopenharmony_ci 4442c593315Sopenharmony_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`. 4452c593315Sopenharmony_ci 4462c593315Sopenharmony_ci#### LICENSE 4472c593315Sopenharmony_ci 4482c593315Sopenharmony_ciThis software is licensed under the MIT License. 4492c593315Sopenharmony_ci 4502c593315Sopenharmony_ciCopyright Fedor Indutny, 2018. 4512c593315Sopenharmony_ci 4522c593315Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a 4532c593315Sopenharmony_cicopy of this software and associated documentation files (the 4542c593315Sopenharmony_ci"Software"), to deal in the Software without restriction, including 4552c593315Sopenharmony_ciwithout limitation the rights to use, copy, modify, merge, publish, 4562c593315Sopenharmony_cidistribute, sublicense, and/or sell copies of the Software, and to permit 4572c593315Sopenharmony_cipersons to whom the Software is furnished to do so, subject to the 4582c593315Sopenharmony_cifollowing conditions: 4592c593315Sopenharmony_ci 4602c593315Sopenharmony_ciThe above copyright notice and this permission notice shall be included 4612c593315Sopenharmony_ciin all copies or substantial portions of the Software. 4622c593315Sopenharmony_ci 4632c593315Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 4642c593315Sopenharmony_ciOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 4652c593315Sopenharmony_ciMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 4662c593315Sopenharmony_ciNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 4672c593315Sopenharmony_ciDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 4682c593315Sopenharmony_ciOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 4692c593315Sopenharmony_ciUSE OR OTHER DEALINGS IN THE SOFTWARE. 4702c593315Sopenharmony_ci 4712c593315Sopenharmony_ci[0]: https://github.com/nodejs/http-parser 4722c593315Sopenharmony_ci[1]: https://github.com/nodejs/llparse 4732c593315Sopenharmony_ci[2]: https://en.wikipedia.org/wiki/Register_allocation#Spilling 4742c593315Sopenharmony_ci[3]: https://en.wikipedia.org/wiki/Tail_call 4752c593315Sopenharmony_ci[4]: https://llvm.org/docs/LangRef.html 4762c593315Sopenharmony_ci[5]: https://llvm.org/docs/LangRef.html#call-instruction 4772c593315Sopenharmony_ci[6]: https://clang.llvm.org/ 4782c593315Sopenharmony_ci[7]: https://github.com/nodejs/node 4792c593315Sopenharmony_ci[8]: https://github.com/pallas/pyllhttp 4802c593315Sopenharmony_ci[9]: https://github.com/metabahn/llhttp 4812c593315Sopenharmony_ci[10]: https://github.com/JackLiar/rust-llhttp 4822c593315Sopenharmony_ci[11]: https://github.com/MunifTanjim/llhttp.lua 483