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, const 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 uint8_t skip_field; /* 1 bit */
59 uint8_t discard_unsafe_fields; /* 1 bit */
60
61 /* target with "/." */
62 uint8_t complex_target; /* 1 bit */
63 #if 0
64 /* target with "%" */
65 uint8_t quoted_target; /* 1 bit */
66 /* target with " " */
67 uint8_t space_in_target; /* 1 bit */
68 #endif
69 /* Preserve encoded '/' (%2F) and '%' (%25). */
70 uint8_t encoded_slashes; /* 1 bit */
71 };
72
73
74 typedef nxt_int_t (*nxt_http_field_handler_t)(void *ctx,
75 nxt_http_field_t *field,
76 uintptr_t data);
77
78
79 typedef struct {
80 nxt_str_t name;
81 nxt_http_field_handler_t handler;
82 uintptr_t data;
83 } nxt_http_field_proc_t;
84
85
86 struct nxt_http_field_s {
87 uint16_t hash;
88 uint8_t skip:1;
89 uint8_t hopbyhop:1;
90 uint8_t name_length;
91 uint32_t value_length;
92 u_char *name;
93 u_char *value;
94 };
95
96
97 typedef struct {
98 u_char *pos;
99 nxt_mp_t *mem_pool;
100
101 uint64_t chunk_size;
102
103 uint8_t state;
104 uint8_t last; /* 1 bit */
105 uint8_t chunk_error; /* 1 bit */
106 uint8_t error; /* 1 bit */
107 } nxt_http_chunk_parse_t;
108
109
110 #define NXT_HTTP_FIELD_HASH_INIT 159406U
111 #define nxt_http_field_hash_char(h, c) (((h) << 4) + (h) + (c))
112 #define nxt_http_field_hash_end(h) (((h) >> 16) ^ (h))
113
114
115 nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp,
116 nxt_mp_t *mp);
117 nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp,
118 nxt_buf_mem_t *b);
119 nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp,
120 nxt_buf_mem_t *b);
121
122 nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash,
123 nxt_http_field_proc_t items[], nxt_uint_t count);
124 nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
125 nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level);
126 nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
127 void *ctx);
128
129 nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
130 nxt_buf_t *in);
131
132
133 extern const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto;
134
135 nxt_inline nxt_int_t
nxt_http_field_process(nxt_http_field_t * field,nxt_lvlhsh_t * hash,void * ctx)136 nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx)
137 {
138 nxt_lvlhsh_query_t lhq;
139 nxt_http_field_proc_t *proc;
140
141 lhq.proto = &nxt_http_fields_hash_proto;
142
143 lhq.key_hash = field->hash;
144 lhq.key.length = field->name_length;
145 lhq.key.start = field->name;
146
147 if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) {
148 return NXT_OK;
149 }
150
151 proc = lhq.value;
152
153 return proc->handler(ctx, field, proc->data);
154 }
155
156
157 #endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */
158