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