xref: /unit/src/nxt_http_parse.h (revision 1709:1fe93c17d23f)
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     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