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