mhd_request.h (13888B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2022-2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/mhd_request.h 41 * @brief The definition of the request data structures 42 * @author Karlson2k (Evgeny Grin) 43 * 44 * Data structures in this header are used when parsing client's request 45 */ 46 47 #ifndef MHD_REQUEST_H 48 #define MHD_REQUEST_H 1 49 50 #include "mhd_sys_options.h" 51 #include "sys_base_types.h" 52 #include "sys_bool_type.h" 53 #include "mhd_public_api.h" 54 55 #include "mhd_dlinked_list.h" 56 57 #include "http_prot_ver.h" 58 #include "http_method.h" 59 #include "mhd_action.h" 60 #include "mhd_buffer.h" 61 62 #ifdef MHD_SUPPORT_POST_PARSER 63 # include "mhd_postfield_int.h" 64 # include "mhd_post_parser.h" 65 #endif 66 67 #ifdef MHD_SUPPORT_HTTP2 68 # include "h2/h2_stream_data.h" 69 #endif 70 71 /** 72 * The request line processing data 73 */ 74 struct MHD_RequestLineProcessing 75 { 76 /** 77 * The position of the next character to be processed 78 */ 79 size_t proc_pos; 80 /** 81 * The number of empty lines skipped 82 */ 83 unsigned int skipped_empty_lines; 84 /** 85 * The position of the start of the current/last found whitespace block, 86 * zero if not found yet. 87 */ 88 size_t last_ws_start; 89 /** 90 * The position of the next character after the last known whitespace 91 * character in the current/last found whitespace block, 92 * zero if not found yet. 93 */ 94 size_t last_ws_end; 95 /** 96 * The pointer to the request target. 97 * The request URI will be formed based on it. 98 */ 99 char *rq_tgt; 100 /** 101 * The pointer to the first question mark in the @a rq_tgt. 102 */ 103 char *rq_tgt_qmark; 104 /** 105 * The number of whitespace characters in the request URI 106 */ 107 size_t num_ws_in_uri; 108 }; 109 110 /** 111 * The request header processing data 112 */ 113 struct MHD_HeaderProcessing 114 { 115 /** 116 * The position of the last processed character 117 */ 118 size_t proc_pos; 119 120 /** 121 * The position of the first whitespace character in current contiguous 122 * whitespace block. 123 * Zero when no whitespace found or found non-whitespace character after 124 * whitespace. 125 * Must be zero, if the current character is not whitespace. 126 */ 127 size_t ws_start; 128 129 /** 130 * Indicates that end of the header (field) name found. 131 * Must be false until the first colon in line is found. 132 */ 133 bool name_end_found; 134 135 /** 136 * The length of the header name. 137 * Must be zero until the first colon in line is found. 138 * Name always starts at zero position. 139 */ 140 size_t name_len; 141 142 /** 143 * The position of the first character of the header value. 144 * Zero when the first character has not been found yet. 145 */ 146 size_t value_start; 147 148 /** 149 * Line starts with whitespace. 150 * It's meaningful only for the first line, as other lines should be handled 151 * as "folded". 152 */ 153 bool starts_with_ws; 154 }; 155 156 /** 157 * The union of request line and header processing data 158 */ 159 union MHD_HeadersProcessing 160 { 161 /** 162 * The request line processing data 163 */ 164 struct MHD_RequestLineProcessing rq_line; 165 166 /** 167 * The request header processing data 168 */ 169 struct MHD_HeaderProcessing hdr; 170 }; 171 172 173 /** 174 * The union of text staring point and the size of the text 175 */ 176 union MHD_StartOrSize 177 { 178 /** 179 * The starting point of the text. 180 * Valid when the text is being processed and the end of the text 181 * is not yet determined. 182 */ 183 const char *start; 184 /** 185 * The size of the text. 186 * Valid when the text has been processed and the end of the text 187 * is known. 188 */ 189 size_t size; 190 }; 191 192 struct mhd_RequestField; /* forward declarations */ 193 194 mhd_DLINKEDL_LINKS_DEF (mhd_RequestField); 195 196 /** 197 * Header, footer, or cookie for HTTP request. 198 */ 199 struct mhd_RequestField 200 { 201 /** 202 * The field data 203 */ 204 struct MHD_NameValueKind field; 205 206 /** 207 * Headers are kept in a double-linked list. 208 */ 209 mhd_DLNKDL_LINKS (mhd_RequestField,fields); 210 }; 211 212 mhd_DLINKEDL_LIST_DEF (mhd_RequestField); 213 214 #ifdef MHD_SUPPORT_POST_PARSER 215 216 struct mhd_RequestPostField; /* forward declarations */ 217 218 mhd_DLINKEDL_LINKS_DEF (mhd_RequestPostField); 219 220 /** 221 * The data for POST request fields 222 */ 223 struct mhd_RequestPostField 224 { 225 /** 226 * The field data 227 */ 228 struct mhd_PostFieldInt field; 229 230 /** 231 * Headers are kept in a double-linked list. 232 */ 233 mhd_DLNKDL_LINKS (mhd_RequestPostField,post_fields); 234 }; 235 236 mhd_DLINKEDL_LIST_DEF (mhd_RequestPostField); 237 238 239 #endif /* MHD_SUPPORT_POST_PARSER */ 240 241 242 /** 243 * The request content data 244 */ 245 struct mhd_ReqContentData 246 { 247 /** 248 * The pointer to the large buffer 249 * Must be NULL if large buffer is not allocated. 250 */ 251 struct mhd_Buffer lbuf; 252 253 /** 254 * 'true' if request has any (even zero-sized) upload (content/body) 255 */ 256 bool cntn_present; 257 258 /** 259 * The total size of the request content. 260 * #MHD_SIZE_UNKNOWN if the size is not yet known (chunked upload). 261 */ 262 uint_fast64_t cntn_size; 263 264 /** 265 * The size of the received content. 266 * Excluding chunked encoding framing. 267 */ 268 uint_fast64_t recv_size; 269 270 /** 271 * The size of the processed content. 272 * Excluding chunked encoding framing. 273 */ 274 uint_fast64_t proc_size; 275 }; 276 277 278 union mhd_ReqContentParsingData 279 { 280 #ifdef MHD_SUPPORT_POST_PARSER 281 /** 282 * The POST parsing data 283 */ 284 struct mhd_PostParserData post; 285 #endif /* MHD_SUPPORT_POST_PARSER */ 286 // TODO: move "raw" upload processing data here 287 }; 288 289 290 #ifdef MHD_SUPPORT_AUTH_BASIC 291 /** 292 * Request Basic Auth internal data 293 * The same format as struct MHD_AuthBasicCreds, but wiht nullable username. 294 * Keep in sync with MHD_AuthBasicCreds! 295 */ 296 struct mhd_ReqAuthBasicInternalData 297 { 298 /** 299 * The user name 300 */ 301 struct MHD_StringNullable username; 302 /** 303 * The user password 304 */ 305 struct MHD_StringNullable password; 306 }; 307 308 /** 309 * Request Basic Auth data 310 */ 311 union mhd_ReqAuthBasicData 312 { 313 /** 314 * The internal representation of the Basic Auth data 315 */ 316 struct mhd_ReqAuthBasicInternalData intr; 317 318 /** 319 * The external (application) Basic Auth data 320 */ 321 struct MHD_AuthBasicCreds extr; 322 }; 323 324 #endif /* MHD_SUPPORT_AUTH_BASIC */ 325 326 #ifdef MHD_SUPPORT_AUTH_DIGEST 327 328 struct mhd_AuthDigesReqParams; /* forward declaration */ 329 330 /** 331 * Request Digest Auth data 332 */ 333 struct mhd_ReqAuthDigestData 334 { 335 /** 336 * Request Digest Auth pre-parsed data 337 */ 338 struct mhd_AuthDigesReqParams *rqp; 339 /** 340 * When set to value other then #MHD_SC_OK, 341 * indicates request Digest Auth header parsing error. 342 */ 343 enum MHD_StatusCode parse_result; 344 /** 345 * The information about client's Digest Auth header. 346 * NULL if not yet parsed or not found. 347 */ 348 struct MHD_AuthDigestInfo *info; 349 }; 350 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 351 352 #if defined(MHD_SUPPORT_AUTH_BASIC) || defined(MHD_SUPPORT_AUTH_DIGEST) 353 /** 354 * Defined if any Authentication scheme is supported 355 */ 356 # define mhd_SUPPORT_AUTH 1 357 #endif /* MHD_SUPPORT_AUTH_BASIC */ 358 359 360 #ifdef mhd_SUPPORT_AUTH 361 /** 362 * Request Basic Auth data 363 */ 364 struct mhd_ReqAuthData 365 { 366 #ifdef MHD_SUPPORT_AUTH_BASIC 367 /** 368 * Request Basic Auth data 369 */ 370 union mhd_ReqAuthBasicData basic; 371 #endif /* MHD_SUPPORT_AUTH_BASIC */ 372 #ifdef MHD_SUPPORT_AUTH_DIGEST 373 /** 374 * Request Digest Auth data 375 */ 376 struct mhd_ReqAuthDigestData digest; 377 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 378 }; 379 380 #endif /* mhd_SUPPORT_AUTH */ 381 382 /** 383 * Request-specific values. 384 * 385 * Meaningful for the current request only. 386 */ 387 struct MHD_Request 388 { 389 #ifdef MHD_SUPPORT_HTTP2 390 /** 391 * Always 'false' in HTTP/1.x requests 392 */ 393 bool is_http2; 394 #endif /* MHD_SUPPORT_HTTP2 */ 395 /** 396 * Linked list of parsed headers. 397 */ 398 mhd_DLNKDL_LIST (mhd_RequestField,fields); 399 400 #ifdef MHD_SUPPORT_POST_PARSER 401 /** 402 * Linked list of parsed POST fields. 403 */ 404 mhd_DLNKDL_LIST (mhd_RequestPostField,post_fields); 405 #endif /* MHD_SUPPORT_POST_PARSER */ 406 407 /** 408 * The action set by the application 409 */ 410 struct mhd_ApplicationAction app_act; 411 412 /** 413 * The request content data 414 */ 415 struct mhd_ReqContentData cntn; 416 417 /** 418 * Set to true if request is too large to be handled 419 */ 420 bool too_large; 421 422 /** 423 * Upload processing data 424 */ 425 union mhd_ReqContentParsingData u_proc; 426 427 /** 428 * Have "Expect: 100-continue" request header 429 */ 430 bool have_expect_100; 431 432 #ifdef mhd_SUPPORT_AUTH 433 /** 434 * Request Basic Auth data 435 */ 436 struct mhd_ReqAuthData auth; 437 #endif /* mhd_SUPPORT_AUTH */ 438 439 /** 440 * HTTP version string (i.e. http/1.1). Allocated 441 * in pool. 442 */ 443 const char *version; 444 445 /** 446 * HTTP protocol version as enum. 447 */ 448 enum MHD_HTTP_ProtocolVersion http_ver; 449 450 /** 451 * Request method. Should be GET/POST/etc. Allocated in pool. 452 */ 453 struct MHD_String method; 454 455 /** 456 * The request method as enum. 457 */ 458 enum mhd_HTTP_Method http_mthd; 459 460 /** 461 * Requested URL, the part before '?' (excluding parameters). Allocated 462 * in pool. 463 */ 464 const char *url; 465 466 /** 467 * The length of the @a url in characters, not including the terminating zero. 468 */ 469 size_t url_len; 470 471 /** 472 * The original length of the request target. 473 */ 474 size_t req_target_len; 475 476 /** 477 * Number of bytes we had in the HTTP header, set once we 478 * pass #mhd_HTTP_STAGE_HEADERS_RECEIVED. 479 * This includes the request line, all request headers, the header section 480 * terminating empty line, with all CRLF (or LF) characters. 481 */ 482 size_t header_size; 483 484 /** 485 * The union of the size of all request field lines (headers) and 486 * the starting point of the first request field line (the first header). 487 * Until #mhd_HTTP_STAGE_HEADERS_RECEIVED the @a start member is valid, 488 * staring with #mhd_HTTP_STAGE_HEADERS_RECEIVED the @a size member is valid. 489 * The size includes CRLF (or LR) characters, but does not include 490 * the terminating empty line. 491 */ 492 union MHD_StartOrSize field_lines; 493 494 /** 495 * Are we receiving with chunked encoding? 496 * This will be set to #MHD_YES after we parse the headers and 497 * are processing the body with chunks. 498 * After we are done with the body and we are processing the footers; 499 * once the footers are also done, this will be set to #MHD_NO again 500 * (before the final call to the handler). 501 * It is used only for requests, chunked encoding for response is 502 * indicated by @a rp_props. 503 */ 504 bool have_chunked_upload; 505 506 /** 507 * If we are receiving with chunked encoding, where are we right 508 * now? 509 * Set to 0 if we are waiting to receive the chunk size; 510 * otherwise, this is the size of the current chunk. 511 * A value of zero is also used when we're at the end of the chunks. 512 */ 513 uint_fast64_t current_chunk_size; 514 515 /** 516 * If we are receiving with chunked encoding, where are we currently 517 * with respect to the current chunk (at what offset / position)? 518 */ 519 uint_fast64_t current_chunk_offset; 520 521 /** 522 * We allow the main application to associate some pointer with the 523 * HTTP request, which is passed to each #MHD_AccessHandlerCallback 524 * and some other API calls. Here is where we store it. (MHD does 525 * not know or care what it is). 526 */ 527 void *app_context; 528 529 /** 530 * Did we ever call the "default_handler" on this request? 531 * This flag determines if we have called the #MHD_OPTION_NOTIFY_COMPLETED 532 * handler when the request finishes. 533 */ 534 bool app_aware; 535 536 /** 537 * Number of bare CR characters that were replaced with space characters 538 * in the request line or in the headers (field lines). 539 */ 540 size_t num_cr_sp_replaced; 541 542 /** 543 * The number of header lines skipped because they have no colon 544 */ 545 size_t skipped_broken_lines; 546 547 /** 548 * The data of the request line / request headers processing 549 */ 550 union MHD_HeadersProcessing hdrs; 551 }; 552 553 #ifdef MHD_SUPPORT_HTTP2 554 # define mhd_REQ_IS_HTTP2(req) ((req)->is_http2) 555 #else /* ! MHD_SUPPORT_HTTP2 */ 556 # define mhd_REQ_IS_HTTP2(req) (! ! 0) 557 #endif /* ! MHD_SUPPORT_HTTP2 */ 558 559 #ifdef MHD_SUPPORT_HTTP2 560 # define mhd_REQ_GET_ACT_UNION(req) \ 561 (mhd_REQ_IS_HTTP2 ((req)) ? \ 562 &(((struct mhd_H2RequestData*) (req))->app_act) : \ 563 &((req)->app_act)) 564 #else /* ! MHD_SUPPORT_HTTP2 */ 565 # define mhd_REQ_GET_ACT_UNION(req) (&((req)->app_act)) 566 #endif /* ! MHD_SUPPORT_HTTP2 */ 567 568 #define mhd_REQ_GET_ACT_HEAD(req) (&(mhd_REQ_GET_ACT_UNION (req)->head_act)) 569 570 #define mhd_REQ_GET_ACT_UPLD(req) (&(mhd_REQ_GET_ACT_UNION (req)->upl_act)) 571 572 #endif /* ! MHD_REQUEST_H */