libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

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 */