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