@@ -92,6 +92,239 @@ if (err == HPE_OK) { |
92 | 92 | ``` |
93 | 93 | For more information on API usage, please refer to [src/native/api.h](https://github.com/nodejs/llhttp/blob/main/src/native/api.h). |
94 | 94 |
|
| 95 | +## API |
| 96 | +
|
| 97 | +### llhttp_settings_t |
| 98 | +
|
| 99 | +The settings object contains a list of callbacks that the parser will invoke. |
| 100 | +
|
| 101 | +The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_PAUSED` (pause the parser): |
| 102 | +
|
| 103 | +* `on_message_begin`: Invoked when a new request/response starts. |
| 104 | +* `on_message_complete`: Invoked when a request/response has been completedly parsed. |
| 105 | +* `on_url_complete`: Invoked after the URL has been parsed. |
| 106 | +* `on_method_complete`: Invoked after the HTTP method has been parsed. |
| 107 | +* `on_version_complete`: Invoked after the HTTP version has been parsed. |
| 108 | +* `on_status_complete`: Invoked after the status code has been parsed. |
| 109 | +* `on_header_field_complete`: Invoked after a header name has been parsed. |
| 110 | +* `on_header_value_complete`: Invoked after a header value has been parsed. |
| 111 | +* `on_chunk_header`: Invoked after a new chunk is started. The current chunk length is stored in `parser->content_length`. |
| 112 | +* `on_chunk_extension_name_complete`: Invoked after a chunk extension name is started. |
| 113 | +* `on_chunk_extension_value_complete`: Invoked after a chunk extension value is started. |
| 114 | +* `on_chunk_complete`: Invoked after a new chunk is received. |
| 115 | +* `on_reset`: Invoked after `on_message_complete` and before `on_message_begin` when a new message |
| 116 | + is received on the same parser. This is not invoked for the first message of the parser. |
| 117 | +
|
| 118 | +The following callbacks can return `0` (proceed normally), `-1` (error) or `HPE_USER` (error from the callback): |
| 119 | +
|
| 120 | +* `on_url`: Invoked when another character of the URL is received. |
| 121 | +* `on_status`: Invoked when another character of the status is received. |
| 122 | +* `on_method`: Invoked when another character of the method is received. |
| 123 | + When parser is created with `HTTP_BOTH` and the input is a response, this also invoked for the sequence `HTTP/` |
| 124 | + of the first message. |
| 125 | +* `on_version`: Invoked when another character of the version is received. |
| 126 | +* `on_header_field`: Invoked when another character of a header name is received. |
| 127 | +* `on_header_value`: Invoked when another character of a header value is received. |
| 128 | +* `on_chunk_extension_name`: Invoked when another character of a chunk extension name is received. |
| 129 | +* `on_chunk_extension_value`: Invoked when another character of a extension value is received. |
| 130 | +
|
| 131 | +The callback `on_headers_complete`, invoked when headers are completed, can return: |
| 132 | +
|
| 133 | +* `0`: Proceed normally. |
| 134 | +* `1`: Assume that request/response has no body, and proceed to parsing the next message. |
| 135 | +* `2`: Assume absence of body (as above) and make `llhttp_execute()` return `HPE_PAUSED_UPGRADE`. |
| 136 | +* `-1`: Error |
| 137 | +* `HPE_PAUSED`: Pause the parser. |
| 138 | +
|
| 139 | +### `void llhttp_init(llhttp_t* parser, llhttp_type_t type, const llhttp_settings_t* settings)` |
| 140 | +
|
| 141 | +Initialize the parser with specific type and user settings. |
| 142 | +
|
| 143 | +### `uint8_t llhttp_get_type(llhttp_t* parser)` |
| 144 | +
|
| 145 | +Returns the type of the parser. |
| 146 | +
|
| 147 | +### `uint8_t llhttp_get_http_major(llhttp_t* parser)` |
| 148 | +
|
| 149 | +Returns the major version of the HTTP protocol of the current request/response. |
| 150 | +
|
| 151 | +### `uint8_t llhttp_get_http_minor(llhttp_t* parser)` |
| 152 | +
|
| 153 | +Returns the minor version of the HTTP protocol of the current request/response. |
| 154 | +
|
| 155 | +### `uint8_t llhttp_get_method(llhttp_t* parser)` |
| 156 | +
|
| 157 | +Returns the method of the current request. |
| 158 | +
|
| 159 | +### `int llhttp_get_status_code(llhttp_t* parser)` |
| 160 | +
|
| 161 | +Returns the method of the current response. |
| 162 | +
|
| 163 | +### `uint8_t llhttp_get_upgrade(llhttp_t* parser)` |
| 164 | +
|
| 165 | +Returns `1` if request includes the `Connection: upgrade` header. |
| 166 | +
|
| 167 | +### `void llhttp_reset(llhttp_t* parser)` |
| 168 | +
|
| 169 | +Reset an already initialized parser back to the start state, preserving the |
| 170 | +existing parser type, callback settings, user data, and lenient flags. |
| 171 | +
|
| 172 | +### `void llhttp_settings_init(llhttp_settings_t* settings)` |
| 173 | +
|
| 174 | +Initialize the settings object. |
| 175 | +
|
| 176 | +### `llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len)` |
| 177 | +
|
| 178 | +Parse full or partial request/response, invoking user callbacks along the way. |
| 179 | +
|
| 180 | +If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing interrupts, |
| 181 | +and such errno is returned from `llhttp_execute()`. If `HPE_PAUSED` was used as a errno, |
| 182 | +the execution can be resumed with `llhttp_resume()` call. |
| 183 | +
|
| 184 | +In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` is returned |
| 185 | +after fully parsing the request/response. If the user wishes to continue parsing, |
| 186 | +they need to invoke `llhttp_resume_after_upgrade()`. |
| 187 | +
|
| 188 | +**if this function ever returns a non-pause type error, it will continue to return |
| 189 | +the same error upon each successive call up until `llhttp_init()` is called.** |
| 190 | +
|
| 191 | +### `llhttp_errno_t llhttp_finish(llhttp_t* parser)` |
| 192 | +
|
| 193 | +This method should be called when the other side has no further bytes to |
| 194 | +send (e.g. shutdown of readable side of the TCP connection.) |
| 195 | +
|
| 196 | +Requests without `Content-Length` and other messages might require treating |
| 197 | +all incoming bytes as the part of the body, up to the last byte of the |
| 198 | +connection. |
| 199 | +
|
| 200 | +This method will invoke `on_message_complete()` callback if the |
| 201 | +request was terminated safely. Otherwise a error code would be returned. |
| 202 | +
|
| 203 | +
|
| 204 | +### `int llhttp_message_needs_eof(const llhttp_t* parser)` |
| 205 | +
|
| 206 | +Returns `1` if the incoming message is parsed until the last byte, and has to be completed by calling `llhttp_finish()` on EOF. |
| 207 | +
|
| 208 | +### `int llhttp_should_keep_alive(const llhttp_t* parser)` |
| 209 | +
|
| 210 | +Returns `1` if there might be any other messages following the last that was |
| 211 | +successfully parsed. |
| 212 | +
|
| 213 | +### `void llhttp_pause(llhttp_t* parser)` |
| 214 | +
|
| 215 | +Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set |
| 216 | +appropriate error reason. |
| 217 | +
|
| 218 | +**Do not call this from user callbacks! User callbacks must return |
| 219 | +`HPE_PAUSED` if pausing is required.** |
| 220 | +
|
| 221 | +### `void llhttp_resume(llhttp_t* parser)` |
| 222 | +
|
| 223 | +Might be called to resume the execution after the pause in user's callback. |
| 224 | +
|
| 225 | +See `llhttp_execute()` above for details. |
| 226 | +
|
| 227 | +**Call this only if `llhttp_execute()` returns `HPE_PAUSED`.** |
| 228 | +
|
| 229 | +### `void llhttp_resume_after_upgrade(llhttp_t* parser)` |
| 230 | +
|
| 231 | +Might be called to resume the execution after the pause in user's callback. |
| 232 | +See `llhttp_execute()` above for details. |
| 233 | +
|
| 234 | +**Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`** |
| 235 | +
|
| 236 | +### `llhttp_errno_t llhttp_get_errno(const llhttp_t* parser)` |
| 237 | +
|
| 238 | +Returns the latest error. |
| 239 | +
|
| 240 | +### `const char* llhttp_get_error_reason(const llhttp_t* parser)` |
| 241 | +
|
| 242 | +Returns the verbal explanation of the latest returned error. |
| 243 | +
|
| 244 | +**User callback should set error reason when returning the error. See |
| 245 | +`llhttp_set_error_reason()` for details.** |
| 246 | +
|
| 247 | +### `void llhttp_set_error_reason(llhttp_t* parser, const char* reason)` |
| 248 | +
|
| 249 | +Assign verbal description to the returned error. Must be called in user |
| 250 | +callbacks right before returning the errno. |
| 251 | +
|
| 252 | +**`HPE_USER` error code might be useful in user callbacks.** |
| 253 | +
|
| 254 | +### `const char* llhttp_get_error_pos(const llhttp_t* parser)` |
| 255 | +
|
| 256 | +Returns the pointer to the last parsed byte before the returned error. The |
| 257 | +pointer is relative to the `data` argument of `llhttp_execute()`. |
| 258 | +
|
| 259 | +**This method might be useful for counting the number of parsed bytes.** |
| 260 | +
|
| 261 | +### `const char* llhttp_errno_name(llhttp_errno_t err)` |
| 262 | +
|
| 263 | +Returns textual name of error code. |
| 264 | +
|
| 265 | +### `const char* llhttp_method_name(llhttp_method_t method)` |
| 266 | +
|
| 267 | +Returns textual name of HTTP method. |
| 268 | +
|
| 269 | +### `const char* llhttp_status_name(llhttp_status_t status)` |
| 270 | +
|
| 271 | +Returns textual name of HTTP status. |
| 272 | +
|
| 273 | +### `void llhttp_set_lenient_headers(llhttp_t* parser, int enabled)` |
| 274 | +
|
| 275 | +Enables/disables lenient header value parsing (disabled by default). |
| 276 | +Lenient parsing disables header value token checks, extending llhttp's |
| 277 | +protocol support to highly non-compliant clients/server. |
| 278 | +
|
| 279 | +No `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when |
| 280 | +lenient parsing is "on". |
| 281 | +
|
| 282 | +**USE AT YOUR OWN RISK!** |
| 283 | +
|
| 284 | +### `void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled)` |
| 285 | +
|
| 286 | +Enables/disables lenient handling of conflicting `Transfer-Encoding` and |
| 287 | +`Content-Length` headers (disabled by default). |
| 288 | +
|
| 289 | +Normally `llhttp` would error when `Transfer-Encoding` is present in |
| 290 | +conjunction with `Content-Length`. |
| 291 | +
|
| 292 | +This error is important to prevent HTTP request smuggling, but may be less desirable |
| 293 | +for small number of cases involving legacy servers. |
| 294 | +
|
| 295 | +**USE AT YOUR OWN RISK!** |
| 296 | +
|
| 297 | +### `void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled)` |
| 298 | +
|
| 299 | +Enables/disables lenient handling of `Connection: close` and HTTP/1.0 |
| 300 | +requests responses. |
| 301 | +
|
| 302 | +Normally `llhttp` would error on (in strict mode) or discard (in loose mode) |
| 303 | +the HTTP request/response after the request/response with `Connection: close` |
| 304 | +and `Content-Length`. |
| 305 | +
|
| 306 | +This is important to prevent cache poisoning attacks, |
| 307 | +but might interact badly with outdated and insecure clients. |
| 308 | +
|
| 309 | +With this flag the extra request/response will be parsed normally. |
| 310 | +
|
| 311 | +**USE AT YOUR OWN RISK!** |
| 312 | +
|
| 313 | +### `void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled)` |
| 314 | +
|
| 315 | +Enables/disables lenient handling of `Transfer-Encoding` header. |
| 316 | +
|
| 317 | +Normally `llhttp` would error when a `Transfer-Encoding` has `chunked` value |
| 318 | +and another value after it (either in a single header or in multiple |
| 319 | +headers whose value are internally joined using `, `). |
| 320 | +
|
| 321 | +This is mandated by the spec to reliably determine request body size and thus |
| 322 | +avoid request smuggling. |
| 323 | +
|
| 324 | +With this flag the extra value will be parsed normally. |
| 325 | +
|
| 326 | +**USE AT YOUR OWN RISK!** |
| 327 | +
|
95 | 328 | ## Build Instructions |
96 | 329 |
|
97 | 330 | Make sure you have [Node.js](https://nodejs.org/), npm and npx installed. Then under project directory run: |
|
105 | 338 |
|
106 | 339 | ### Bindings to other languages |
107 | 340 |
|
| 341 | +* Lua: [MunifTanjim/llhttp.lua][11] |
108 | 342 | * Python: [pallas/pyllhttp][8] |
109 | 343 | * Ruby: [metabahn/llhttp][9] |
110 | 344 | * Rust: [JackLiar/rust-llhttp][10] |
@@ -180,3 +414,4 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. |
180 | 414 | [8]: https://github.com/pallas/pyllhttp |
181 | 415 | [9]: https://github.com/metabahn/llhttp |
182 | 416 | [10]: https://github.com/JackLiar/rust-llhttp |
| 417 | +[11]: https://github.com/MunifTanjim/llhttp.lua |