1 2 /* 3 * Copyright (C) NGINX, Inc. 4 * Copyright (C) Valentin V. Bartenev 5 */ 6 7 #ifndef _NXT_HTTP_PARSER_H_INCLUDED_ 8 #define _NXT_HTTP_PARSER_H_INCLUDED_ 9 10 11 typedef enum { 12 NXT_HTTP_PARSE_INVALID = 1, 13 NXT_HTTP_PARSE_UNSUPPORTED_VERSION, 14 NXT_HTTP_PARSE_TOO_LARGE_FIELD, 15 } nxt_http_parse_error_t; 16 17 18 typedef struct nxt_http_request_parse_s nxt_http_request_parse_t; 19 typedef struct nxt_http_field_s nxt_http_field_t; 20 typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t; 21 22 23 typedef union { 24 u_char str[8]; 25 uint64_t ui64; 26 27 struct { 28 u_char prefix[5]; 29 u_char major; 30 u_char point; 31 u_char minor; 32 } s; 33 } nxt_http_ver_t; 34 35 36 struct nxt_http_request_parse_s { 37 nxt_int_t (*handler)(nxt_http_request_parse_t *rp, 38 u_char **pos, u_char *end); 39 40 nxt_str_t method; 41 42 u_char *target_start; 43 u_char *target_end; 44 45 nxt_str_t path; 46 nxt_str_t args; 47 48 nxt_http_ver_t version; 49 50 nxt_list_t *fields; 51 nxt_mp_t *mem_pool; 52 53 nxt_str_t field_name; 54 nxt_str_t field_value; 55 56 uint32_t field_hash; 57 58 /* target with "/." */ 59 uint8_t complex_target; /* 1 bit */ 60 /* target with "%" */ 61 uint8_t quoted_target; /* 1 bit */ 62 /* target with " " */ 63 uint8_t space_in_target; /* 1 bit */ 64 65 /* Preserve encoded '/' (%2F) and '%' (%25). */ 66 uint8_t encoded_slashes; /* 1 bit */ 67 }; 68 69 70 typedef nxt_int_t (*nxt_http_field_handler_t)(void *ctx, 71 nxt_http_field_t *field, 72 uintptr_t data); 73 74 75 typedef struct { 76 nxt_str_t name; 77 nxt_http_field_handler_t handler; 78 uintptr_t data; 79 } nxt_http_field_proc_t; 80 81 82 struct nxt_http_field_s { 83 uint16_t hash; 84 uint8_t skip:1; 85 uint8_t hopbyhop:1; 86 uint8_t name_length; 87 uint32_t value_length; 88 u_char *name; 89 u_char *value; 90 }; 91 92 93 typedef struct { 94 u_char *pos; 95 nxt_mp_t *mem_pool; 96 97 uint64_t chunk_size; 98 99 uint8_t state; 100 uint8_t last; /* 1 bit */ 101 uint8_t chunk_error; /* 1 bit */ 102 uint8_t error; /* 1 bit */ 103 } nxt_http_chunk_parse_t; 104 105 106 #define NXT_HTTP_FIELD_HASH_INIT 159406U 107 #define nxt_http_field_hash_char(h, c) (((h) << 4) + (h) + (c)) 108 #define nxt_http_field_hash_end(h) (((h) >> 16) ^ (h)) 109 110 111 nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp, 112 nxt_mp_t *mp); 113 nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp, 114 nxt_buf_mem_t *b); 115 nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp, 116 nxt_buf_mem_t *b); 117 118 nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash, 119 nxt_http_field_proc_t items[], nxt_uint_t count); 120 nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, 121 nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level); 122 nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, 123 void *ctx); 124 125 nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, 126 nxt_buf_t *in); 127 128 129 extern const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto; 130 131 nxt_inline nxt_int_t 132 nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx) 133 { 134 nxt_lvlhsh_query_t lhq; 135 nxt_http_field_proc_t *proc; 136 137 lhq.proto = &nxt_http_fields_hash_proto; 138 139 lhq.key_hash = field->hash; 140 lhq.key.length = field->name_length; 141 lhq.key.start = field->name; 142 143 if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) { 144 return NXT_OK; 145 } 146 147 proc = lhq.value; 148 149 return proc->handler(ctx, field, proc->data); 150 } 151 152 153 #endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */ 154