1 #ifndef INCLUDE_LLHTTP_H_ 2 #define INCLUDE_LLHTTP_H_ 3 4 #define LLHTTP_VERSION_MAJOR 6 5 #define LLHTTP_VERSION_MINOR 0 6 #define LLHTTP_VERSION_PATCH 11 7 8 #ifndef LLHTTP_STRICT_MODE 9 # define LLHTTP_STRICT_MODE 0 10 #endif 11 12 #ifndef INCLUDE_LLHTTP_ITSELF_H_ 13 #define INCLUDE_LLHTTP_ITSELF_H_ 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 #include <stdint.h> 19 20 typedef struct llhttp__internal_s llhttp__internal_t; 21 struct llhttp__internal_s { 22 int32_t _index; 23 void* _span_pos0; 24 void* _span_cb0; 25 int32_t error; 26 const char* reason; 27 const char* error_pos; 28 void* data; 29 void* _current; 30 uint64_t content_length; 31 uint8_t type; 32 uint8_t method; 33 uint8_t http_major; 34 uint8_t http_minor; 35 uint8_t header_state; 36 uint8_t lenient_flags; 37 uint8_t upgrade; 38 uint8_t finish; 39 uint16_t flags; 40 uint16_t status_code; 41 void* settings; 42 }; 43 44 int llhttp__internal_init(llhttp__internal_t* s); 45 int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp); 46 47 #ifdef __cplusplus 48 } /* extern "C" */ 49 #endif 50 #endif /* INCLUDE_LLHTTP_ITSELF_H_ */ 51 52 #ifndef LLLLHTTP_C_HEADERS_ 53 #define LLLLHTTP_C_HEADERS_ 54 #ifdef __cplusplus 55 extern "C" { 56 #endif 57 58 enum llhttp_errno { 59 HPE_OK = 0, 60 HPE_INTERNAL = 1, 61 HPE_STRICT = 2, 62 HPE_CR_EXPECTED = 25, 63 HPE_LF_EXPECTED = 3, 64 HPE_UNEXPECTED_CONTENT_LENGTH = 4, 65 HPE_CLOSED_CONNECTION = 5, 66 HPE_INVALID_METHOD = 6, 67 HPE_INVALID_URL = 7, 68 HPE_INVALID_CONSTANT = 8, 69 HPE_INVALID_VERSION = 9, 70 HPE_INVALID_HEADER_TOKEN = 10, 71 HPE_INVALID_CONTENT_LENGTH = 11, 72 HPE_INVALID_CHUNK_SIZE = 12, 73 HPE_INVALID_STATUS = 13, 74 HPE_INVALID_EOF_STATE = 14, 75 HPE_INVALID_TRANSFER_ENCODING = 15, 76 HPE_CB_MESSAGE_BEGIN = 16, 77 HPE_CB_HEADERS_COMPLETE = 17, 78 HPE_CB_MESSAGE_COMPLETE = 18, 79 HPE_CB_CHUNK_HEADER = 19, 80 HPE_CB_CHUNK_COMPLETE = 20, 81 HPE_PAUSED = 21, 82 HPE_PAUSED_UPGRADE = 22, 83 HPE_PAUSED_H2_UPGRADE = 23, 84 HPE_USER = 24 85 }; 86 typedef enum llhttp_errno llhttp_errno_t; 87 88 enum llhttp_flags { 89 F_CONNECTION_KEEP_ALIVE = 0x1, 90 F_CONNECTION_CLOSE = 0x2, 91 F_CONNECTION_UPGRADE = 0x4, 92 F_CHUNKED = 0x8, 93 F_UPGRADE = 0x10, 94 F_CONTENT_LENGTH = 0x20, 95 F_SKIPBODY = 0x40, 96 F_TRAILING = 0x80, 97 F_TRANSFER_ENCODING = 0x200 98 }; 99 typedef enum llhttp_flags llhttp_flags_t; 100 101 enum llhttp_lenient_flags { 102 LENIENT_HEADERS = 0x1, 103 LENIENT_CHUNKED_LENGTH = 0x2, 104 LENIENT_KEEP_ALIVE = 0x4, 105 LENIENT_TRANSFER_ENCODING = 0x8, 106 LENIENT_VERSION = 0x10 107 }; 108 typedef enum llhttp_lenient_flags llhttp_lenient_flags_t; 109 110 enum llhttp_type { 111 HTTP_BOTH = 0, 112 HTTP_REQUEST = 1, 113 HTTP_RESPONSE = 2 114 }; 115 typedef enum llhttp_type llhttp_type_t; 116 117 enum llhttp_finish { 118 HTTP_FINISH_SAFE = 0, 119 HTTP_FINISH_SAFE_WITH_CB = 1, 120 HTTP_FINISH_UNSAFE = 2 121 }; 122 typedef enum llhttp_finish llhttp_finish_t; 123 124 enum llhttp_method { 125 HTTP_DELETE = 0, 126 HTTP_GET = 1, 127 HTTP_HEAD = 2, 128 HTTP_POST = 3, 129 HTTP_PUT = 4, 130 HTTP_CONNECT = 5, 131 HTTP_OPTIONS = 6, 132 HTTP_TRACE = 7, 133 HTTP_COPY = 8, 134 HTTP_LOCK = 9, 135 HTTP_MKCOL = 10, 136 HTTP_MOVE = 11, 137 HTTP_PROPFIND = 12, 138 HTTP_PROPPATCH = 13, 139 HTTP_SEARCH = 14, 140 HTTP_UNLOCK = 15, 141 HTTP_BIND = 16, 142 HTTP_REBIND = 17, 143 HTTP_UNBIND = 18, 144 HTTP_ACL = 19, 145 HTTP_REPORT = 20, 146 HTTP_MKACTIVITY = 21, 147 HTTP_CHECKOUT = 22, 148 HTTP_MERGE = 23, 149 HTTP_MSEARCH = 24, 150 HTTP_NOTIFY = 25, 151 HTTP_SUBSCRIBE = 26, 152 HTTP_UNSUBSCRIBE = 27, 153 HTTP_PATCH = 28, 154 HTTP_PURGE = 29, 155 HTTP_MKCALENDAR = 30, 156 HTTP_LINK = 31, 157 HTTP_UNLINK = 32, 158 HTTP_SOURCE = 33, 159 HTTP_PRI = 34, 160 HTTP_DESCRIBE = 35, 161 HTTP_ANNOUNCE = 36, 162 HTTP_SETUP = 37, 163 HTTP_PLAY = 38, 164 HTTP_PAUSE = 39, 165 HTTP_TEARDOWN = 40, 166 HTTP_GET_PARAMETER = 41, 167 HTTP_SET_PARAMETER = 42, 168 HTTP_REDIRECT = 43, 169 HTTP_RECORD = 44, 170 HTTP_FLUSH = 45 171 }; 172 typedef enum llhttp_method llhttp_method_t; 173 174 #define HTTP_ERRNO_MAP(XX) \ 175 XX(0, OK, OK) \ 176 XX(1, INTERNAL, INTERNAL) \ 177 XX(2, STRICT, STRICT) \ 178 XX(25, CR_EXPECTED, CR_EXPECTED) \ 179 XX(3, LF_EXPECTED, LF_EXPECTED) \ 180 XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \ 181 XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \ 182 XX(6, INVALID_METHOD, INVALID_METHOD) \ 183 XX(7, INVALID_URL, INVALID_URL) \ 184 XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \ 185 XX(9, INVALID_VERSION, INVALID_VERSION) \ 186 XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \ 187 XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \ 188 XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \ 189 XX(13, INVALID_STATUS, INVALID_STATUS) \ 190 XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \ 191 XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \ 192 XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \ 193 XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \ 194 XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \ 195 XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \ 196 XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ 197 XX(21, PAUSED, PAUSED) \ 198 XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ 199 XX(23, PAUSED_H2_UPGRADE, PAUSED_H2_UPGRADE) \ 200 XX(24, USER, USER) \ 201 202 203 #define HTTP_METHOD_MAP(XX) \ 204 XX(0, DELETE, DELETE) \ 205 XX(1, GET, GET) \ 206 XX(2, HEAD, HEAD) \ 207 XX(3, POST, POST) \ 208 XX(4, PUT, PUT) \ 209 XX(5, CONNECT, CONNECT) \ 210 XX(6, OPTIONS, OPTIONS) \ 211 XX(7, TRACE, TRACE) \ 212 XX(8, COPY, COPY) \ 213 XX(9, LOCK, LOCK) \ 214 XX(10, MKCOL, MKCOL) \ 215 XX(11, MOVE, MOVE) \ 216 XX(12, PROPFIND, PROPFIND) \ 217 XX(13, PROPPATCH, PROPPATCH) \ 218 XX(14, SEARCH, SEARCH) \ 219 XX(15, UNLOCK, UNLOCK) \ 220 XX(16, BIND, BIND) \ 221 XX(17, REBIND, REBIND) \ 222 XX(18, UNBIND, UNBIND) \ 223 XX(19, ACL, ACL) \ 224 XX(20, REPORT, REPORT) \ 225 XX(21, MKACTIVITY, MKACTIVITY) \ 226 XX(22, CHECKOUT, CHECKOUT) \ 227 XX(23, MERGE, MERGE) \ 228 XX(24, MSEARCH, M-SEARCH) \ 229 XX(25, NOTIFY, NOTIFY) \ 230 XX(26, SUBSCRIBE, SUBSCRIBE) \ 231 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 232 XX(28, PATCH, PATCH) \ 233 XX(29, PURGE, PURGE) \ 234 XX(30, MKCALENDAR, MKCALENDAR) \ 235 XX(31, LINK, LINK) \ 236 XX(32, UNLINK, UNLINK) \ 237 XX(33, SOURCE, SOURCE) \ 238 239 240 #define RTSP_METHOD_MAP(XX) \ 241 XX(1, GET, GET) \ 242 XX(3, POST, POST) \ 243 XX(6, OPTIONS, OPTIONS) \ 244 XX(35, DESCRIBE, DESCRIBE) \ 245 XX(36, ANNOUNCE, ANNOUNCE) \ 246 XX(37, SETUP, SETUP) \ 247 XX(38, PLAY, PLAY) \ 248 XX(39, PAUSE, PAUSE) \ 249 XX(40, TEARDOWN, TEARDOWN) \ 250 XX(41, GET_PARAMETER, GET_PARAMETER) \ 251 XX(42, SET_PARAMETER, SET_PARAMETER) \ 252 XX(43, REDIRECT, REDIRECT) \ 253 XX(44, RECORD, RECORD) \ 254 XX(45, FLUSH, FLUSH) \ 255 256 257 #define HTTP_ALL_METHOD_MAP(XX) \ 258 XX(0, DELETE, DELETE) \ 259 XX(1, GET, GET) \ 260 XX(2, HEAD, HEAD) \ 261 XX(3, POST, POST) \ 262 XX(4, PUT, PUT) \ 263 XX(5, CONNECT, CONNECT) \ 264 XX(6, OPTIONS, OPTIONS) \ 265 XX(7, TRACE, TRACE) \ 266 XX(8, COPY, COPY) \ 267 XX(9, LOCK, LOCK) \ 268 XX(10, MKCOL, MKCOL) \ 269 XX(11, MOVE, MOVE) \ 270 XX(12, PROPFIND, PROPFIND) \ 271 XX(13, PROPPATCH, PROPPATCH) \ 272 XX(14, SEARCH, SEARCH) \ 273 XX(15, UNLOCK, UNLOCK) \ 274 XX(16, BIND, BIND) \ 275 XX(17, REBIND, REBIND) \ 276 XX(18, UNBIND, UNBIND) \ 277 XX(19, ACL, ACL) \ 278 XX(20, REPORT, REPORT) \ 279 XX(21, MKACTIVITY, MKACTIVITY) \ 280 XX(22, CHECKOUT, CHECKOUT) \ 281 XX(23, MERGE, MERGE) \ 282 XX(24, MSEARCH, M-SEARCH) \ 283 XX(25, NOTIFY, NOTIFY) \ 284 XX(26, SUBSCRIBE, SUBSCRIBE) \ 285 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 286 XX(28, PATCH, PATCH) \ 287 XX(29, PURGE, PURGE) \ 288 XX(30, MKCALENDAR, MKCALENDAR) \ 289 XX(31, LINK, LINK) \ 290 XX(32, UNLINK, UNLINK) \ 291 XX(33, SOURCE, SOURCE) \ 292 XX(34, PRI, PRI) \ 293 XX(35, DESCRIBE, DESCRIBE) \ 294 XX(36, ANNOUNCE, ANNOUNCE) \ 295 XX(37, SETUP, SETUP) \ 296 XX(38, PLAY, PLAY) \ 297 XX(39, PAUSE, PAUSE) \ 298 XX(40, TEARDOWN, TEARDOWN) \ 299 XX(41, GET_PARAMETER, GET_PARAMETER) \ 300 XX(42, SET_PARAMETER, SET_PARAMETER) \ 301 XX(43, REDIRECT, REDIRECT) \ 302 XX(44, RECORD, RECORD) \ 303 XX(45, FLUSH, FLUSH) \ 304 305 306 #ifdef __cplusplus 307 } /* extern "C" */ 308 #endif 309 #endif /* LLLLHTTP_C_HEADERS_ */ 310 311 #ifndef INCLUDE_LLHTTP_API_H_ 312 #define INCLUDE_LLHTTP_API_H_ 313 #ifdef __cplusplus 314 extern "C" { 315 #endif 316 #include <stddef.h> 317 318 #if defined(__wasm__) 319 #define LLHTTP_EXPORT __attribute__((visibility("default"))) 320 #else 321 #define LLHTTP_EXPORT 322 #endif 323 324 typedef llhttp__internal_t llhttp_t; 325 typedef struct llhttp_settings_s llhttp_settings_t; 326 327 typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length); 328 typedef int (*llhttp_cb)(llhttp_t*); 329 330 struct llhttp_settings_s { 331 /* Possible return values 0, -1, `HPE_PAUSED` */ 332 llhttp_cb on_message_begin; 333 334 /* Possible return values 0, -1, HPE_USER */ 335 llhttp_data_cb on_url; 336 llhttp_data_cb on_status; 337 llhttp_data_cb on_header_field; 338 llhttp_data_cb on_header_value; 339 340 /* Possible return values: 341 * 0 - Proceed normally 342 * 1 - Assume that request/response has no body, and proceed to parsing the 343 * next message 344 * 2 - Assume absence of body (as above) and make `llhttp_execute()` return 345 * `HPE_PAUSED_UPGRADE` 346 * -1 - Error 347 * `HPE_PAUSED` 348 */ 349 llhttp_cb on_headers_complete; 350 351 /* Possible return values 0, -1, HPE_USER */ 352 llhttp_data_cb on_body; 353 354 /* Possible return values 0, -1, `HPE_PAUSED` */ 355 llhttp_cb on_message_complete; 356 357 /* When on_chunk_header is called, the current chunk length is stored 358 * in parser->content_length. 359 * Possible return values 0, -1, `HPE_PAUSED` 360 */ 361 llhttp_cb on_chunk_header; 362 llhttp_cb on_chunk_complete; 363 364 /* Information-only callbacks, return value is ignored */ 365 llhttp_cb on_url_complete; 366 llhttp_cb on_status_complete; 367 llhttp_cb on_header_field_complete; 368 llhttp_cb on_header_value_complete; 369 }; 370 371 /* Initialize the parser with specific type and user settings. 372 * 373 * NOTE: lifetime of `settings` has to be at least the same as the lifetime of 374 * the `parser` here. In practice, `settings` has to be either a static 375 * variable or be allocated with `malloc`, `new`, etc. 376 */ 377 LLHTTP_EXPORT 378 void llhttp_init(llhttp_t* parser, llhttp_type_t type, 379 const llhttp_settings_t* settings); 380 381 LLHTTP_EXPORT 382 llhttp_t* llhttp_alloc(llhttp_type_t type); 383 384 LLHTTP_EXPORT 385 void llhttp_free(llhttp_t* parser); 386 387 LLHTTP_EXPORT 388 uint8_t llhttp_get_type(llhttp_t* parser); 389 390 LLHTTP_EXPORT 391 uint8_t llhttp_get_http_major(llhttp_t* parser); 392 393 LLHTTP_EXPORT 394 uint8_t llhttp_get_http_minor(llhttp_t* parser); 395 396 LLHTTP_EXPORT 397 uint8_t llhttp_get_method(llhttp_t* parser); 398 399 LLHTTP_EXPORT 400 int llhttp_get_status_code(llhttp_t* parser); 401 402 LLHTTP_EXPORT 403 uint8_t llhttp_get_upgrade(llhttp_t* parser); 404 405 /* Reset an already initialized parser back to the start state, preserving the 406 * existing parser type, callback settings, user data, and lenient flags. 407 */ 408 LLHTTP_EXPORT 409 void llhttp_reset(llhttp_t* parser); 410 411 /* Initialize the settings object */ 412 LLHTTP_EXPORT 413 void llhttp_settings_init(llhttp_settings_t* settings); 414 415 /* Parse full or partial request/response, invoking user callbacks along the 416 * way. 417 * 418 * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing 419 * interrupts, and such errno is returned from `llhttp_execute()`. If 420 * `HPE_PAUSED` was used as a errno, the execution can be resumed with 421 * `llhttp_resume()` call. 422 * 423 * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` 424 * is returned after fully parsing the request/response. If the user wishes to 425 * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`. 426 * 427 * NOTE: if this function ever returns a non-pause type error, it will continue 428 * to return the same error upon each successive call up until `llhttp_init()` 429 * is called. 430 */ 431 LLHTTP_EXPORT 432 llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); 433 434 /* This method should be called when the other side has no further bytes to 435 * send (e.g. shutdown of readable side of the TCP connection.) 436 * 437 * Requests without `Content-Length` and other messages might require treating 438 * all incoming bytes as the part of the body, up to the last byte of the 439 * connection. This method will invoke `on_message_complete()` callback if the 440 * request was terminated safely. Otherwise a error code would be returned. 441 */ 442 LLHTTP_EXPORT 443 llhttp_errno_t llhttp_finish(llhttp_t* parser); 444 445 /* Returns `1` if the incoming message is parsed until the last byte, and has 446 * to be completed by calling `llhttp_finish()` on EOF 447 */ 448 LLHTTP_EXPORT 449 int llhttp_message_needs_eof(const llhttp_t* parser); 450 451 /* Returns `1` if there might be any other messages following the last that was 452 * successfully parsed. 453 */ 454 LLHTTP_EXPORT 455 int llhttp_should_keep_alive(const llhttp_t* parser); 456 457 /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set 458 * appropriate error reason. 459 * 460 * Important: do not call this from user callbacks! User callbacks must return 461 * `HPE_PAUSED` if pausing is required. 462 */ 463 LLHTTP_EXPORT 464 void llhttp_pause(llhttp_t* parser); 465 466 /* Might be called to resume the execution after the pause in user's callback. 467 * See `llhttp_execute()` above for details. 468 * 469 * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. 470 */ 471 LLHTTP_EXPORT 472 void llhttp_resume(llhttp_t* parser); 473 474 /* Might be called to resume the execution after the pause in user's callback. 475 * See `llhttp_execute()` above for details. 476 * 477 * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` 478 */ 479 LLHTTP_EXPORT 480 void llhttp_resume_after_upgrade(llhttp_t* parser); 481 482 /* Returns the latest return error */ 483 LLHTTP_EXPORT 484 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); 485 486 /* Returns the verbal explanation of the latest returned error. 487 * 488 * Note: User callback should set error reason when returning the error. See 489 * `llhttp_set_error_reason()` for details. 490 */ 491 LLHTTP_EXPORT 492 const char* llhttp_get_error_reason(const llhttp_t* parser); 493 494 /* Assign verbal description to the returned error. Must be called in user 495 * callbacks right before returning the errno. 496 * 497 * Note: `HPE_USER` error code might be useful in user callbacks. 498 */ 499 LLHTTP_EXPORT 500 void llhttp_set_error_reason(llhttp_t* parser, const char* reason); 501 502 /* Returns the pointer to the last parsed byte before the returned error. The 503 * pointer is relative to the `data` argument of `llhttp_execute()`. 504 * 505 * Note: this method might be useful for counting the number of parsed bytes. 506 */ 507 LLHTTP_EXPORT 508 const char* llhttp_get_error_pos(const llhttp_t* parser); 509 510 /* Returns textual name of error code */ 511 LLHTTP_EXPORT 512 const char* llhttp_errno_name(llhttp_errno_t err); 513 514 /* Returns textual name of HTTP method */ 515 LLHTTP_EXPORT 516 const char* llhttp_method_name(llhttp_method_t method); 517 518 519 /* Enables/disables lenient header value parsing (disabled by default). 520 * 521 * Lenient parsing disables header value token checks, extending llhttp's 522 * protocol support to highly non-compliant clients/server. No 523 * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when 524 * lenient parsing is "on". 525 * 526 * **(USE AT YOUR OWN RISK)** 527 */ 528 LLHTTP_EXPORT 529 void llhttp_set_lenient_headers(llhttp_t* parser, int enabled); 530 531 532 /* Enables/disables lenient handling of conflicting `Transfer-Encoding` and 533 * `Content-Length` headers (disabled by default). 534 * 535 * Normally `llhttp` would error when `Transfer-Encoding` is present in 536 * conjunction with `Content-Length`. This error is important to prevent HTTP 537 * request smuggling, but may be less desirable for small number of cases 538 * involving legacy servers. 539 * 540 * **(USE AT YOUR OWN RISK)** 541 */ 542 LLHTTP_EXPORT 543 void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled); 544 545 546 /* Enables/disables lenient handling of `Connection: close` and HTTP/1.0 547 * requests responses. 548 * 549 * Normally `llhttp` would error on (in strict mode) or discard (in loose mode) 550 * the HTTP request/response after the request/response with `Connection: close` 551 * and `Content-Length`. This is important to prevent cache poisoning attacks, 552 * but might interact badly with outdated and insecure clients. With this flag 553 * the extra request/response will be parsed normally. 554 * 555 * **(USE AT YOUR OWN RISK)** 556 */ 557 void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled); 558 559 /* Enables/disables lenient handling of `Transfer-Encoding` header. 560 * 561 * Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value 562 * and another value after it (either in a single header or in multiple 563 * headers whose value are internally joined using `, `). 564 * This is mandated by the spec to reliably determine request body size and thus 565 * avoid request smuggling. 566 * With this flag the extra value will be parsed normally. 567 * 568 * **(USE AT YOUR OWN RISK)** 569 */ 570 void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled); 571 572 #ifdef __cplusplus 573 } /* extern "C" */ 574 #endif 575 #endif /* INCLUDE_LLHTTP_API_H_ */ 576 577 #endif /* INCLUDE_LLHTTP_H_ */ 578