1bcdc6a3bSJan Kneschke #ifndef _REQUEST_H_ 2bcdc6a3bSJan Kneschke #define _REQUEST_H_ 38abd06a7SGlenn Strauss #include "first.h" 4bcdc6a3bSJan Kneschke 513ea2d88SGlenn Strauss #include "sys-time.h" /* (struct timespec) */ 66fe031efSGlenn Strauss 704d76e7aSGlenn Strauss #include "base_decls.h" 804d76e7aSGlenn Strauss #include "buffer.h" 9668cb641SGlenn Strauss #include "array.h" 1081029b8bSGlenn Strauss #include "chunk.h" 11668cb641SGlenn Strauss #include "http_kv.h" 12668cb641SGlenn Strauss 131474be78SGlenn Strauss struct chunkqueue; /* declaration */ 148131e439SGlenn Strauss struct cond_cache_t; /* declaration */ 158131e439SGlenn Strauss struct cond_match_t; /* declaration */ 169a5e1652SGlenn Strauss struct stat_cache_entry;/* declaration */ 17668cb641SGlenn Strauss 18d5366c0aSGlenn Strauss typedef struct request_config { 198071b803SGlenn Strauss fdlog_st *errh; 207c7f8c46SGlenn Strauss unsigned int http_parseopts; 217c7f8c46SGlenn Strauss uint32_t max_request_field_size; 22668cb641SGlenn Strauss const array *mimetypes; 23668cb641SGlenn Strauss 24668cb641SGlenn Strauss /* virtual-servers */ 25668cb641SGlenn Strauss const buffer *document_root; 26668cb641SGlenn Strauss const buffer *server_name; 27668cb641SGlenn Strauss const buffer *server_tag; 28668cb641SGlenn Strauss 297c7f8c46SGlenn Strauss unsigned int max_request_size; 30668cb641SGlenn Strauss unsigned short max_keep_alive_requests; 31668cb641SGlenn Strauss unsigned short max_keep_alive_idle; 32668cb641SGlenn Strauss unsigned short max_read_idle; 33668cb641SGlenn Strauss unsigned short max_write_idle; 34668cb641SGlenn Strauss unsigned short stream_request_body; 35668cb641SGlenn Strauss unsigned short stream_response_body; 368071b803SGlenn Strauss unsigned int high_precision_timestamps:1; 378071b803SGlenn Strauss unsigned int allow_http11:1; 388071b803SGlenn Strauss unsigned int range_requests:1; 398071b803SGlenn Strauss unsigned int follow_symlink:1; 408071b803SGlenn Strauss unsigned int etag_flags:3; 418071b803SGlenn Strauss unsigned int use_xattr:1; 428071b803SGlenn Strauss unsigned int force_lowercase_filenames:2;/*(case-insensitive file systems)*/ 438071b803SGlenn Strauss unsigned int error_intercept:1; 44668cb641SGlenn Strauss 458071b803SGlenn Strauss unsigned int h2proto:2; /*(global setting copied for convenient access)*/ 461041a56dSGlenn Strauss 47668cb641SGlenn Strauss /* debug */ 488071b803SGlenn Strauss unsigned int log_request_handling:1; 498071b803SGlenn Strauss unsigned int log_state_handling:1; 508071b803SGlenn Strauss unsigned int log_condition_handling:1; 518071b803SGlenn Strauss unsigned int log_response_header:1; 528071b803SGlenn Strauss unsigned int log_request_header:1; 538071b803SGlenn Strauss unsigned int log_request_header_on_error:1; 548071b803SGlenn Strauss unsigned int log_file_not_found:1; 558071b803SGlenn Strauss unsigned int log_timeouts:1; 56668cb641SGlenn Strauss 57668cb641SGlenn Strauss unsigned int bytes_per_second; /* connection bytes/sec limit */ 58668cb641SGlenn Strauss unsigned int global_bytes_per_second;/*total bytes/sec limit for scope*/ 59668cb641SGlenn Strauss 60668cb641SGlenn Strauss /* server-wide traffic-shaper 61668cb641SGlenn Strauss * 62668cb641SGlenn Strauss * each context has the counter which is inited once 63668cb641SGlenn Strauss * a second by the global_bytes_per_second config-var 64668cb641SGlenn Strauss * 65668cb641SGlenn Strauss * as soon as global_bytes_per_second gets below 0 66668cb641SGlenn Strauss * the connected conns are "offline" a little bit 67668cb641SGlenn Strauss * 68668cb641SGlenn Strauss * the problem: 69668cb641SGlenn Strauss * we somehow have to lose our "we are writable" signal on the way. 70668cb641SGlenn Strauss * 71668cb641SGlenn Strauss */ 72668cb641SGlenn Strauss off_t *global_bytes_per_second_cnt_ptr; /* */ 73668cb641SGlenn Strauss 74668cb641SGlenn Strauss const buffer *error_handler; 75668cb641SGlenn Strauss const buffer *error_handler_404; 76668cb641SGlenn Strauss const buffer *errorfile_prefix; 777b615d5dSGlenn Strauss fdlog_st *serrh; /* script errh */ 78668cb641SGlenn Strauss } request_config; 79668cb641SGlenn Strauss 807c7f8c46SGlenn Strauss typedef struct { 817c7f8c46SGlenn Strauss buffer scheme; /* scheme without colon or slashes ( "http" or "https" ) */ 827c7f8c46SGlenn Strauss 837c7f8c46SGlenn Strauss /* authority with optional portnumber ("site.name" or "site.name:8080" ) NOTE: without "username:password@" */ 847c7f8c46SGlenn Strauss buffer authority; 857c7f8c46SGlenn Strauss 867c7f8c46SGlenn Strauss /* path including leading slash ("/" or "/index.html") - urldecoded, and sanitized ( buffer_path_simplify() && buffer_urldecode_path() ) */ 877c7f8c46SGlenn Strauss buffer path; 887c7f8c46SGlenn Strauss buffer query; /* querystring ( everything after "?", ie: in "/index.php?foo=1", query is "foo=1" ) */ 897c7f8c46SGlenn Strauss } request_uri; 907c7f8c46SGlenn Strauss 917c7f8c46SGlenn Strauss typedef struct { 927c7f8c46SGlenn Strauss buffer path; 937c7f8c46SGlenn Strauss buffer basedir; /* path = "(basedir)(.*)" */ 947c7f8c46SGlenn Strauss 957c7f8c46SGlenn Strauss buffer doc_root; /* path = doc_root + rel_path */ 967c7f8c46SGlenn Strauss buffer rel_path; 977c7f8c46SGlenn Strauss } physical; 987c7f8c46SGlenn Strauss 997420526dSGlenn Strauss typedef struct { 1007420526dSGlenn Strauss off_t gw_chunked; 1017420526dSGlenn Strauss buffer b; 1027420526dSGlenn Strauss int done; 1037420526dSGlenn Strauss } response_dechunk; 1047420526dSGlenn Strauss 105aca9d45aSGlenn Strauss /* the order of the items should be the same as they are processed 106aca9d45aSGlenn Strauss * read before write as we use this later e.g. <= CON_STATE_REQUEST_END */ 1075e0d82dcSGlenn Strauss /* NB: must sync with http_request_state_short(), http_request_state_append() */ 108aca9d45aSGlenn Strauss typedef enum { 109aca9d45aSGlenn Strauss CON_STATE_CONNECT, 110aca9d45aSGlenn Strauss CON_STATE_REQUEST_START, 111aca9d45aSGlenn Strauss CON_STATE_READ, 112aca9d45aSGlenn Strauss CON_STATE_REQUEST_END, 113aca9d45aSGlenn Strauss CON_STATE_READ_POST, 114aca9d45aSGlenn Strauss CON_STATE_HANDLE_REQUEST, 115aca9d45aSGlenn Strauss CON_STATE_RESPONSE_START, 116aca9d45aSGlenn Strauss CON_STATE_WRITE, 117aca9d45aSGlenn Strauss CON_STATE_RESPONSE_END, 118aca9d45aSGlenn Strauss CON_STATE_ERROR, 119aca9d45aSGlenn Strauss CON_STATE_CLOSE 120aca9d45aSGlenn Strauss } request_state_t; 121aca9d45aSGlenn Strauss 1226870b0f5SGlenn Strauss struct request_st { 123aca9d45aSGlenn Strauss request_state_t state; /*(modules should not modify request state)*/ 1247c7f8c46SGlenn Strauss int http_status; 1256eca864cSGlenn Strauss uint32_t h2state; /*(modules should not modify request h2state)*/ 1266eca864cSGlenn Strauss uint32_t h2id; 1276eca864cSGlenn Strauss int32_t h2_rwin; 1286eca864cSGlenn Strauss int32_t h2_swin; 129ad4a7904SGlenn Strauss int16_t h2_rwin_fudge; 1309a3f6c52SGlenn Strauss uint8_t h2_prio; 131668cb641SGlenn Strauss 132668cb641SGlenn Strauss http_method_t http_method; 133668cb641SGlenn Strauss http_version_t http_version; 1347c7f8c46SGlenn Strauss 1357c7f8c46SGlenn Strauss const plugin *handler_module; 136100dfaa3SGlenn Strauss void **plugin_ctx; /* plugin connection specific config */ 1377c7f8c46SGlenn Strauss connection *con; 138668cb641SGlenn Strauss 1397c7f8c46SGlenn Strauss /* config conditions (internal) */ 1408131e439SGlenn Strauss uint32_t conditional_is_valid; 1418131e439SGlenn Strauss struct cond_cache_t *cond_cache; 1427ea2d407SGlenn Strauss struct cond_match_t **cond_match; 1437ea2d407SGlenn Strauss struct cond_match_t *cond_match_data; 144a22cdca1SGlenn Strauss 1457c7f8c46SGlenn Strauss request_config conf; 1467c7f8c46SGlenn Strauss 1477c7f8c46SGlenn Strauss /* request */ 1487c7f8c46SGlenn Strauss uint32_t rqst_header_len; 149367f30a6SGlenn Strauss uint64_t rqst_htags;/* bitfield of flagged headers present in request */ 1507c7f8c46SGlenn Strauss array rqst_headers; 1517c7f8c46SGlenn Strauss 1527c7f8c46SGlenn Strauss request_uri uri; 1537c7f8c46SGlenn Strauss physical physical; 154a22cdca1SGlenn Strauss array env; /* used to pass lighttpd internal stuff */ 155a22cdca1SGlenn Strauss 1567c7f8c46SGlenn Strauss off_t reqbody_length; /* request Content-Length */ 1577c7f8c46SGlenn Strauss off_t te_chunked; 158903024d7SGlenn Strauss off_t resp_body_scratchpad; 159a22cdca1SGlenn Strauss 1607c7f8c46SGlenn Strauss buffer *http_host; /* copy of array value buffer ptr; not alloc'ed */ 1617c7f8c46SGlenn Strauss const buffer *server_name; 1627c7f8c46SGlenn Strauss 1637c7f8c46SGlenn Strauss buffer target; 1647c7f8c46SGlenn Strauss buffer target_orig; 1657c7f8c46SGlenn Strauss 1667c7f8c46SGlenn Strauss buffer pathinfo; 1677c7f8c46SGlenn Strauss buffer server_name_buf; 1687c7f8c46SGlenn Strauss 169*3a8fc4bcSGlenn Strauss void *dst_addr; 170*3a8fc4bcSGlenn Strauss buffer *dst_addr_buf; 171*3a8fc4bcSGlenn Strauss 1727c7f8c46SGlenn Strauss /* response */ 1737c7f8c46SGlenn Strauss uint32_t resp_header_len; 174367f30a6SGlenn Strauss uint64_t resp_htags; /*bitfield of flagged headers present in response*/ 1757c7f8c46SGlenn Strauss array resp_headers; 1767c7f8c46SGlenn Strauss char resp_body_finished; 1777c7f8c46SGlenn Strauss char resp_body_started; 1787c7f8c46SGlenn Strauss char resp_send_chunked; 1797420526dSGlenn Strauss char resp_decode_chunked; 180ada09a23SGlenn Strauss char resp_header_repeated; 1817c7f8c46SGlenn Strauss 1827c7f8c46SGlenn Strauss char loops_per_request; /* catch endless loops in a single request */ 1834a600dabSGlenn Strauss int8_t keep_alive; /* only request.c can enable it, all other just disable */ 1847c7f8c46SGlenn Strauss char async_callback; 1857c7f8c46SGlenn Strauss 1867c7f8c46SGlenn Strauss buffer *tmp_buf; /* shared; same as srv->tmp_buf */ 1877420526dSGlenn Strauss response_dechunk *gw_dechunk; 1887c7f8c46SGlenn Strauss 189afc2025dSGlenn Strauss off_t bytes_written_ckpt; /* used by mod_accesslog */ 190afc2025dSGlenn Strauss off_t bytes_read_ckpt; /* used by mod_accesslog */ 191309c1693SGlenn Strauss unix_timespec64_t start_hp; 1927c7f8c46SGlenn Strauss 1937c7f8c46SGlenn Strauss int error_handler_saved_status; /* error-handler */ 1947c7f8c46SGlenn Strauss http_method_t error_handler_saved_method; /* error-handler */ 19581029b8bSGlenn Strauss 19681029b8bSGlenn Strauss struct chunkqueue write_queue; /* HTTP response queue [ file, mem ] */ 19781029b8bSGlenn Strauss struct chunkqueue read_queue; /* HTTP request queue [ mem ] */ 19881029b8bSGlenn Strauss struct chunkqueue reqbody_queue; /*(might use tempfiles)*/ 1999a5e1652SGlenn Strauss 2009a5e1652SGlenn Strauss struct stat_cache_entry *tmp_sce; /*(value valid only in sequential code)*/ 201ef9608f3SGlenn Strauss int cond_captures; 2025d1aa5d0SGlenn Strauss int h2_connect_ext; 2036870b0f5SGlenn Strauss }; 204668cb641SGlenn Strauss 205bcdc6a3bSJan Kneschke 2068fc8ab89SGlenn Strauss typedef struct http_header_parse_ctx { 2078fc8ab89SGlenn Strauss char *k; 2088fc8ab89SGlenn Strauss char *v; 2098fc8ab89SGlenn Strauss uint32_t klen; 2108fc8ab89SGlenn Strauss uint32_t vlen; 2118fc8ab89SGlenn Strauss uint32_t hlen; 2123fbb5773SGlenn Strauss uint8_t pseudo; 2133fbb5773SGlenn Strauss uint8_t scheme; 2143fbb5773SGlenn Strauss uint8_t trailers; 2150f90a9e3SGlenn Strauss int8_t id; 2168fc8ab89SGlenn Strauss uint32_t max_request_field_size; 2178fc8ab89SGlenn Strauss unsigned int http_parseopts; 2188fc8ab89SGlenn Strauss } http_header_parse_ctx; 2198fc8ab89SGlenn Strauss 2208fc8ab89SGlenn Strauss 2218fc8ab89SGlenn Strauss int http_request_validate_pseudohdrs (request_st * restrict r, int scheme, unsigned int http_parseopts); 2228fc8ab89SGlenn Strauss int http_request_parse_header (request_st * restrict r, http_header_parse_ctx * restrict hpctx); 2238fc8ab89SGlenn Strauss void http_request_headers_process_h2 (request_st * restrict r, int scheme_port); 2246971c6c8SGlenn Strauss void http_request_headers_process (request_st * restrict r, char * restrict hdrs, const unsigned short * restrict hoff, int scheme_port); 225d013d0abSGlenn Strauss int http_request_parse_target(request_st *r, int scheme_port); 22640f72a41SGlenn Strauss int http_request_host_normalize(buffer *b, int scheme_port); 2271dd58c5aSGlenn Strauss int http_request_host_policy(buffer *b, unsigned int http_parseopts, int scheme_port); 228bcdc6a3bSJan Kneschke 229e9309ae6SGlenn Strauss int64_t li_restricted_strtoint64 (const char *v, const uint32_t vlen, const char ** const err); 230e9309ae6SGlenn Strauss 2315e0d82dcSGlenn Strauss 2325e0d82dcSGlenn Strauss /* convenience macros/functions for display purposes */ 2335e0d82dcSGlenn Strauss 2345e0d82dcSGlenn Strauss #define http_request_state_is_keep_alive(r) \ 2355e0d82dcSGlenn Strauss (CON_STATE_READ == (r)->state && !buffer_is_blank(&(r)->target_orig)) 2365e0d82dcSGlenn Strauss 2375e0d82dcSGlenn Strauss #define http_con_state_is_keep_alive(con) \ 2385e0d82dcSGlenn Strauss ((con)->h2 \ 2395e0d82dcSGlenn Strauss ? 0 == (con)->h2->rused \ 2405e0d82dcSGlenn Strauss : http_request_state_is_keep_alive(&(con)->request)) 2415e0d82dcSGlenn Strauss 2425e0d82dcSGlenn Strauss #define http_con_state_append(b, con) \ 2435e0d82dcSGlenn Strauss (http_con_state_is_keep_alive(con) \ 2445e0d82dcSGlenn Strauss ? buffer_append_string_len((b), CONST_STR_LEN("keep-alive")) \ 2455e0d82dcSGlenn Strauss : http_request_state_append((b), (con)->request.state)) 2465e0d82dcSGlenn Strauss 2475e0d82dcSGlenn Strauss #define http_con_state_short(con) \ 2485e0d82dcSGlenn Strauss (http_con_state_is_keep_alive(con) \ 2495e0d82dcSGlenn Strauss ? "k" \ 2505e0d82dcSGlenn Strauss : http_request_state_short((con)->request.state)) 2515e0d82dcSGlenn Strauss 2522adc62e9SGlenn Strauss #define http_request_stats_bytes_in(r) \ 2532adc62e9SGlenn Strauss ((r)->read_queue.bytes_out - (r)->bytes_read_ckpt) 2542adc62e9SGlenn Strauss 2552adc62e9SGlenn Strauss #define http_request_stats_bytes_out(r) \ 2562adc62e9SGlenn Strauss ((r)->write_queue.bytes_out - (r)->bytes_written_ckpt) 2572adc62e9SGlenn Strauss 2585e0d82dcSGlenn Strauss __attribute_pure__ 2595e0d82dcSGlenn Strauss const char * http_request_state_short (request_state_t state); 2605e0d82dcSGlenn Strauss 2615e0d82dcSGlenn Strauss void http_request_state_append (buffer *b, request_state_t state); 2625e0d82dcSGlenn Strauss 2635e0d82dcSGlenn Strauss 264bcdc6a3bSJan Kneschke #endif 265