libmicrohttpd2

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

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