summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_http_parse.h
blob: 4aa1c258b5e2644d7a347e730bbd75a757c93c48 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

/*
 * Copyright (C) NGINX, Inc.
 * Copyright (C) Valentin V. Bartenev
 */

#ifndef _NXT_HTTP_PARSER_H_INCLUDED_
#define _NXT_HTTP_PARSER_H_INCLUDED_


typedef enum {
    NXT_HTTP_PARSE_INVALID = 1,
    NXT_HTTP_PARSE_UNSUPPORTED_VERSION,
    NXT_HTTP_PARSE_TOO_LARGE_FIELD,
} nxt_http_parse_error_t;


typedef struct nxt_http_request_parse_s  nxt_http_request_parse_t;
typedef struct nxt_http_field_s          nxt_http_field_t;
typedef struct nxt_http_fields_hash_s    nxt_http_fields_hash_t;


typedef union {
    u_char                    str[8];
    uint64_t                  ui64;

    struct {
        u_char                prefix[5];
        u_char                major;
        u_char                point;
        u_char                minor;
    } s;
} nxt_http_ver_t;


struct nxt_http_request_parse_s {
    nxt_int_t                 (*handler)(nxt_http_request_parse_t *rp,
                                         u_char **pos, const u_char *end);

    nxt_str_t                 method;

    u_char                    *target_start;
    u_char                    *target_end;

    nxt_str_t                 path;
    nxt_str_t                 args;

    nxt_http_ver_t            version;

    nxt_list_t                *fields;
    nxt_mp_t                  *mem_pool;

    nxt_str_t                 field_name;
    nxt_str_t                 field_value;

    uint32_t                  field_hash;

    nxt_bool_t                skip_field;
    nxt_bool_t                discard_unsafe_fields;

    /* target with "/." */
    nxt_bool_t                complex_target;
#if 0
    /* target with "%" */
    nxt_bool_t                quoted_target;
    /* target with " " */
    nxt_bool_t                space_in_target;
#endif
    /* Preserve encoded '/' (%2F) and '%' (%25). */
    nxt_bool_t                encoded_slashes;
};


typedef nxt_int_t (*nxt_http_field_handler_t)(void *ctx,
                                              nxt_http_field_t *field,
                                              uintptr_t data);


typedef struct {
    nxt_str_t                 name;
    nxt_http_field_handler_t  handler;
    uintptr_t                 data;
} nxt_http_field_proc_t;


struct nxt_http_field_s {
    uint16_t                  hash;
    uint8_t                   skip:1;
    uint8_t                   hopbyhop:1;
    uint8_t                   name_length;
    uint32_t                  value_length;
    u_char                    *name;
    u_char                    *value;
};


typedef struct {
    u_char                    *pos;
    nxt_mp_t                  *mem_pool;

    uint64_t                  chunk_size;

    uint8_t                   state;
    nxt_bool_t                last;
    nxt_bool_t                chunk_error;
    nxt_bool_t                error;
} nxt_http_chunk_parse_t;


#define NXT_HTTP_FIELD_HASH_INIT        159406U
#define nxt_http_field_hash_char(h, c)  (((h) << 4) + (h) + (c))
#define nxt_http_field_hash_end(h)      (((h) >> 16) ^ (h))


nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp,
    nxt_mp_t *mp);
nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp,
    nxt_buf_mem_t *b);
nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp,
    nxt_buf_mem_t *b);

nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash,
    nxt_http_field_proc_t items[], nxt_uint_t count);
nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
    nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level);
nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
    void *ctx);

nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
    nxt_buf_t *in);


extern const nxt_lvlhsh_proto_t  nxt_http_fields_hash_proto;

nxt_inline nxt_int_t
nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx)
{
    nxt_lvlhsh_query_t     lhq;
    nxt_http_field_proc_t  *proc;

    lhq.proto = &nxt_http_fields_hash_proto;

    lhq.key_hash = field->hash;
    lhq.key.length = field->name_length;
    lhq.key.start = field->name;

    if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) {
        return NXT_OK;
    }

    proc = lhq.value;

    return proc->handler(ctx, field, proc->data);
}


#endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */