xref: /unit/src/nxt_http_parse.h (revision 2448:243735980417)
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