1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_http.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevstatic uint32_t  usual[] = {
14e18a033bSKonstantin Ananyev    0xffffdbfe, /* 1111 1111 1111 1111  1101 1011 1111 1110 */
15e18a033bSKonstantin Ananyev
16e18a033bSKonstantin Ananyev                /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
17e18a033bSKonstantin Ananyev    0x7fff37d6, /* 0111 1111 1111 1111  0011 0111 1101 0110 */
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyev                /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
20e18a033bSKonstantin Ananyev#if (NGX_WIN32)
21e18a033bSKonstantin Ananyev    0xefffffff, /* 1110 1111 1111 1111  1111 1111 1111 1111 */
22e18a033bSKonstantin Ananyev#else
23e18a033bSKonstantin Ananyev    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
24e18a033bSKonstantin Ananyev#endif
25e18a033bSKonstantin Ananyev
26e18a033bSKonstantin Ananyev                /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
27e18a033bSKonstantin Ananyev    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
28e18a033bSKonstantin Ananyev
29e18a033bSKonstantin Ananyev    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
30e18a033bSKonstantin Ananyev    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
31e18a033bSKonstantin Ananyev    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
32e18a033bSKonstantin Ananyev    0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
33e18a033bSKonstantin Ananyev};
34e18a033bSKonstantin Ananyev
35e18a033bSKonstantin Ananyev
36e18a033bSKonstantin Ananyev#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyev#define ngx_str3_cmp(m, c0, c1, c2, c3)                                       \
39e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev#define ngx_str3Ocmp(m, c0, c1, c2, c3)                                       \
42e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
43e18a033bSKonstantin Ananyev
44e18a033bSKonstantin Ananyev#define ngx_str4cmp(m, c0, c1, c2, c3)                                        \
45e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
46e18a033bSKonstantin Ananyev
47e18a033bSKonstantin Ananyev#define ngx_str5cmp(m, c0, c1, c2, c3, c4)                                    \
48e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
49e18a033bSKonstantin Ananyev        && m[4] == c4
50e18a033bSKonstantin Ananyev
51e18a033bSKonstantin Ananyev#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5)                                \
52e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
53e18a033bSKonstantin Ananyev        && (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4)
54e18a033bSKonstantin Ananyev
55e18a033bSKonstantin Ananyev#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                       \
56e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
57e18a033bSKonstantin Ananyev        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)
58e18a033bSKonstantin Ananyev
59e18a033bSKonstantin Ananyev#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                        \
60e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
61e18a033bSKonstantin Ananyev        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                    \
64e18a033bSKonstantin Ananyev    *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)             \
65e18a033bSKonstantin Ananyev        && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)  \
66e18a033bSKonstantin Ananyev        && m[8] == c8
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev#else /* !(NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) */
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev#define ngx_str3_cmp(m, c0, c1, c2, c3)                                       \
71e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2
72e18a033bSKonstantin Ananyev
73e18a033bSKonstantin Ananyev#define ngx_str3Ocmp(m, c0, c1, c2, c3)                                       \
74e18a033bSKonstantin Ananyev    m[0] == c0 && m[2] == c2 && m[3] == c3
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyev#define ngx_str4cmp(m, c0, c1, c2, c3)                                        \
77e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyev#define ngx_str5cmp(m, c0, c1, c2, c3, c4)                                    \
80e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4
81e18a033bSKonstantin Ananyev
82e18a033bSKonstantin Ananyev#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5)                                \
83e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
84e18a033bSKonstantin Ananyev        && m[4] == c4 && m[5] == c5
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                       \
87e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
88e18a033bSKonstantin Ananyev        && m[4] == c4 && m[5] == c5 && m[6] == c6
89e18a033bSKonstantin Ananyev
90e18a033bSKonstantin Ananyev#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7)                        \
91e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
92e18a033bSKonstantin Ananyev        && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7
93e18a033bSKonstantin Ananyev
94e18a033bSKonstantin Ananyev#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8)                    \
95e18a033bSKonstantin Ananyev    m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3                      \
96e18a033bSKonstantin Ananyev        && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev#endif
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyev
101e18a033bSKonstantin Ananyev/* gcc, icc, msvc and others compile these switches as an jump table */
102e18a033bSKonstantin Ananyev
103e18a033bSKonstantin Ananyevngx_int_t
104e18a033bSKonstantin Ananyevngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
105e18a033bSKonstantin Ananyev{
106e18a033bSKonstantin Ananyev    u_char  c, ch, *p, *m;
107e18a033bSKonstantin Ananyev    enum {
108e18a033bSKonstantin Ananyev        sw_start = 0,
109e18a033bSKonstantin Ananyev        sw_method,
110e18a033bSKonstantin Ananyev        sw_spaces_before_uri,
111e18a033bSKonstantin Ananyev        sw_schema,
112e18a033bSKonstantin Ananyev        sw_schema_slash,
113e18a033bSKonstantin Ananyev        sw_schema_slash_slash,
114e18a033bSKonstantin Ananyev        sw_host_start,
115e18a033bSKonstantin Ananyev        sw_host,
116e18a033bSKonstantin Ananyev        sw_host_end,
117e18a033bSKonstantin Ananyev        sw_host_ip_literal,
118e18a033bSKonstantin Ananyev        sw_port,
119e18a033bSKonstantin Ananyev        sw_host_http_09,
120e18a033bSKonstantin Ananyev        sw_after_slash_in_uri,
121e18a033bSKonstantin Ananyev        sw_check_uri,
122e18a033bSKonstantin Ananyev        sw_check_uri_http_09,
123e18a033bSKonstantin Ananyev        sw_uri,
124e18a033bSKonstantin Ananyev        sw_http_09,
125e18a033bSKonstantin Ananyev        sw_http_H,
126e18a033bSKonstantin Ananyev        sw_http_HT,
127e18a033bSKonstantin Ananyev        sw_http_HTT,
128e18a033bSKonstantin Ananyev        sw_http_HTTP,
129e18a033bSKonstantin Ananyev        sw_first_major_digit,
130e18a033bSKonstantin Ananyev        sw_major_digit,
131e18a033bSKonstantin Ananyev        sw_first_minor_digit,
132e18a033bSKonstantin Ananyev        sw_minor_digit,
133e18a033bSKonstantin Ananyev        sw_spaces_after_digit,
134e18a033bSKonstantin Ananyev        sw_almost_done
135e18a033bSKonstantin Ananyev    } state;
136e18a033bSKonstantin Ananyev
137e18a033bSKonstantin Ananyev    state = r->state;
138e18a033bSKonstantin Ananyev
139e18a033bSKonstantin Ananyev    for (p = b->pos; p < b->last; p++) {
140e18a033bSKonstantin Ananyev        ch = *p;
141e18a033bSKonstantin Ananyev
142e18a033bSKonstantin Ananyev        switch (state) {
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev        /* HTTP methods: GET, HEAD, POST */
145e18a033bSKonstantin Ananyev        case sw_start:
146e18a033bSKonstantin Ananyev            r->request_start = p;
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev            if (ch == CR || ch == LF) {
149e18a033bSKonstantin Ananyev                break;
150e18a033bSKonstantin Ananyev            }
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev            if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
153e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_METHOD;
154e18a033bSKonstantin Ananyev            }
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev            state = sw_method;
157e18a033bSKonstantin Ananyev            break;
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev        case sw_method:
160e18a033bSKonstantin Ananyev            if (ch == ' ') {
161e18a033bSKonstantin Ananyev                r->method_end = p - 1;
162e18a033bSKonstantin Ananyev                m = r->request_start;
163e18a033bSKonstantin Ananyev
164e18a033bSKonstantin Ananyev                switch (p - m) {
165e18a033bSKonstantin Ananyev
166e18a033bSKonstantin Ananyev                case 3:
167e18a033bSKonstantin Ananyev                    if (ngx_str3_cmp(m, 'G', 'E', 'T', ' ')) {
168e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_GET;
169e18a033bSKonstantin Ananyev                        break;
170e18a033bSKonstantin Ananyev                    }
171e18a033bSKonstantin Ananyev
172e18a033bSKonstantin Ananyev                    if (ngx_str3_cmp(m, 'P', 'U', 'T', ' ')) {
173e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_PUT;
174e18a033bSKonstantin Ananyev                        break;
175e18a033bSKonstantin Ananyev                    }
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev                    break;
178e18a033bSKonstantin Ananyev
179e18a033bSKonstantin Ananyev                case 4:
180e18a033bSKonstantin Ananyev                    if (m[1] == 'O') {
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev                        if (ngx_str3Ocmp(m, 'P', 'O', 'S', 'T')) {
183e18a033bSKonstantin Ananyev                            r->method = NGX_HTTP_POST;
184e18a033bSKonstantin Ananyev                            break;
185e18a033bSKonstantin Ananyev                        }
186e18a033bSKonstantin Ananyev
187e18a033bSKonstantin Ananyev                        if (ngx_str3Ocmp(m, 'C', 'O', 'P', 'Y')) {
188e18a033bSKonstantin Ananyev                            r->method = NGX_HTTP_COPY;
189e18a033bSKonstantin Ananyev                            break;
190e18a033bSKonstantin Ananyev                        }
191e18a033bSKonstantin Ananyev
192e18a033bSKonstantin Ananyev                        if (ngx_str3Ocmp(m, 'M', 'O', 'V', 'E')) {
193e18a033bSKonstantin Ananyev                            r->method = NGX_HTTP_MOVE;
194e18a033bSKonstantin Ananyev                            break;
195e18a033bSKonstantin Ananyev                        }
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev                        if (ngx_str3Ocmp(m, 'L', 'O', 'C', 'K')) {
198e18a033bSKonstantin Ananyev                            r->method = NGX_HTTP_LOCK;
199e18a033bSKonstantin Ananyev                            break;
200e18a033bSKonstantin Ananyev                        }
201e18a033bSKonstantin Ananyev
202e18a033bSKonstantin Ananyev                    } else {
203e18a033bSKonstantin Ananyev
204e18a033bSKonstantin Ananyev                        if (ngx_str4cmp(m, 'H', 'E', 'A', 'D')) {
205e18a033bSKonstantin Ananyev                            r->method = NGX_HTTP_HEAD;
206e18a033bSKonstantin Ananyev                            break;
207e18a033bSKonstantin Ananyev                        }
208e18a033bSKonstantin Ananyev                    }
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyev                    break;
211e18a033bSKonstantin Ananyev
212e18a033bSKonstantin Ananyev                case 5:
213e18a033bSKonstantin Ananyev                    if (ngx_str5cmp(m, 'M', 'K', 'C', 'O', 'L')) {
214e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_MKCOL;
215e18a033bSKonstantin Ananyev                        break;
216e18a033bSKonstantin Ananyev                    }
217e18a033bSKonstantin Ananyev
218e18a033bSKonstantin Ananyev                    if (ngx_str5cmp(m, 'P', 'A', 'T', 'C', 'H')) {
219e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_PATCH;
220e18a033bSKonstantin Ananyev                        break;
221e18a033bSKonstantin Ananyev                    }
222e18a033bSKonstantin Ananyev
223e18a033bSKonstantin Ananyev                    if (ngx_str5cmp(m, 'T', 'R', 'A', 'C', 'E')) {
224e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_TRACE;
225e18a033bSKonstantin Ananyev                        break;
226e18a033bSKonstantin Ananyev                    }
227e18a033bSKonstantin Ananyev
228e18a033bSKonstantin Ananyev                    break;
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev                case 6:
231e18a033bSKonstantin Ananyev                    if (ngx_str6cmp(m, 'D', 'E', 'L', 'E', 'T', 'E')) {
232e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_DELETE;
233e18a033bSKonstantin Ananyev                        break;
234e18a033bSKonstantin Ananyev                    }
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev                    if (ngx_str6cmp(m, 'U', 'N', 'L', 'O', 'C', 'K')) {
237e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_UNLOCK;
238e18a033bSKonstantin Ananyev                        break;
239e18a033bSKonstantin Ananyev                    }
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyev                    break;
242e18a033bSKonstantin Ananyev
243e18a033bSKonstantin Ananyev                case 7:
244e18a033bSKonstantin Ananyev                    if (ngx_str7_cmp(m, 'O', 'P', 'T', 'I', 'O', 'N', 'S', ' '))
245e18a033bSKonstantin Ananyev                    {
246e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_OPTIONS;
247e18a033bSKonstantin Ananyev                    }
248e18a033bSKonstantin Ananyev
249e18a033bSKonstantin Ananyev                    break;
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev                case 8:
252e18a033bSKonstantin Ananyev                    if (ngx_str8cmp(m, 'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D'))
253e18a033bSKonstantin Ananyev                    {
254e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_PROPFIND;
255e18a033bSKonstantin Ananyev                    }
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev                    break;
258e18a033bSKonstantin Ananyev
259e18a033bSKonstantin Ananyev                case 9:
260e18a033bSKonstantin Ananyev                    if (ngx_str9cmp(m,
261e18a033bSKonstantin Ananyev                            'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H'))
262e18a033bSKonstantin Ananyev                    {
263e18a033bSKonstantin Ananyev                        r->method = NGX_HTTP_PROPPATCH;
264e18a033bSKonstantin Ananyev                    }
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev                    break;
267e18a033bSKonstantin Ananyev                }
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev                state = sw_spaces_before_uri;
270e18a033bSKonstantin Ananyev                break;
271e18a033bSKonstantin Ananyev            }
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev            if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
274e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_METHOD;
275e18a033bSKonstantin Ananyev            }
276e18a033bSKonstantin Ananyev
277e18a033bSKonstantin Ananyev            break;
278e18a033bSKonstantin Ananyev
279e18a033bSKonstantin Ananyev        /* space* before URI */
280e18a033bSKonstantin Ananyev        case sw_spaces_before_uri:
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyev            if (ch == '/') {
283e18a033bSKonstantin Ananyev                r->uri_start = p;
284e18a033bSKonstantin Ananyev                state = sw_after_slash_in_uri;
285e18a033bSKonstantin Ananyev                break;
286e18a033bSKonstantin Ananyev            }
287e18a033bSKonstantin Ananyev
288e18a033bSKonstantin Ananyev            c = (u_char) (ch | 0x20);
289e18a033bSKonstantin Ananyev            if (c >= 'a' && c <= 'z') {
290e18a033bSKonstantin Ananyev                r->schema_start = p;
291e18a033bSKonstantin Ananyev                state = sw_schema;
292e18a033bSKonstantin Ananyev                break;
293e18a033bSKonstantin Ananyev            }
294e18a033bSKonstantin Ananyev
295e18a033bSKonstantin Ananyev            switch (ch) {
296e18a033bSKonstantin Ananyev            case ' ':
297e18a033bSKonstantin Ananyev                break;
298e18a033bSKonstantin Ananyev            default:
299e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_REQUEST;
300e18a033bSKonstantin Ananyev            }
301e18a033bSKonstantin Ananyev            break;
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev        case sw_schema:
304e18a033bSKonstantin Ananyev
305e18a033bSKonstantin Ananyev            c = (u_char) (ch | 0x20);
306e18a033bSKonstantin Ananyev            if (c >= 'a' && c <= 'z') {
307e18a033bSKonstantin Ananyev                break;
308e18a033bSKonstantin Ananyev            }
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev            switch (ch) {
311e18a033bSKonstantin Ananyev            case ':':
312e18a033bSKonstantin Ananyev                r->schema_end = p;
313e18a033bSKonstantin Ananyev                state = sw_schema_slash;
314e18a033bSKonstantin Ananyev                break;
315e18a033bSKonstantin Ananyev            default:
316e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_REQUEST;
317e18a033bSKonstantin Ananyev            }
318e18a033bSKonstantin Ananyev            break;
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyev        case sw_schema_slash:
321e18a033bSKonstantin Ananyev            switch (ch) {
322e18a033bSKonstantin Ananyev            case '/':
323e18a033bSKonstantin Ananyev                state = sw_schema_slash_slash;
324e18a033bSKonstantin Ananyev                break;
325e18a033bSKonstantin Ananyev            default:
326e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_REQUEST;
327e18a033bSKonstantin Ananyev            }
328e18a033bSKonstantin Ananyev            break;
329e18a033bSKonstantin Ananyev
330e18a033bSKonstantin Ananyev        case sw_schema_slash_slash:
331e18a033bSKonstantin Ananyev            switch (ch) {
332e18a033bSKonstantin Ananyev            case '/':
333e18a033bSKonstantin Ananyev                state = sw_host_start;
334e18a033bSKonstantin Ananyev                break;
335e18a033bSKonstantin Ananyev            default:
336e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_REQUEST;
337e18a033bSKonstantin Ananyev            }
338e18a033bSKonstantin Ananyev            break;
339e18a033bSKonstantin Ananyev
340e18a033bSKonstantin Ananyev        case sw_host_start:
341e18a033bSKonstantin Ananyev
342e18a033bSKonstantin Ananyev            r->host_start = p;
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev            if (ch == '[') {
345e18a033bSKonstantin Ananyev                state = sw_host_ip_literal;
346e18a033bSKonstantin Ananyev                break;
347e18a033bSKonstantin Ananyev            }
348e18a033bSKonstantin Ananyev
349e18a033bSKonstantin Ananyev            state = sw_host;
350e18a033bSKonstantin Ananyev
351e18a033bSKonstantin Ananyev            /* fall through */
352e18a033bSKonstantin Ananyev
353e18a033bSKonstantin Ananyev        case sw_host:
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev            c = (u_char) (ch | 0x20);
356e18a033bSKonstantin Ananyev            if (c >= 'a' && c <= 'z') {
357e18a033bSKonstantin Ananyev                break;
358e18a033bSKonstantin Ananyev            }
359e18a033bSKonstantin Ananyev
360e18a033bSKonstantin Ananyev            if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') {
361e18a033bSKonstantin Ananyev                break;
362e18a033bSKonstantin Ananyev            }
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev            /* fall through */
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev        case sw_host_end:
367e18a033bSKonstantin Ananyev
368e18a033bSKonstantin Ananyev            r->host_end = p;
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev            switch (ch) {
371e18a033bSKonstantin Ananyev            case ':':
372e18a033bSKonstantin Ananyev                state = sw_port;
373e18a033bSKonstantin Ananyev                break;
374e18a033bSKonstantin Ananyev            case '/':
375e18a033bSKonstantin Ananyev                r->uri_start = p;
376e18a033bSKonstantin Ananyev                state = sw_after_slash_in_uri;
377e18a033bSKonstantin Ananyev                break;
378e18a033bSKonstantin Ananyev            case ' ':
379e18a033bSKonstantin Ananyev                /*
380e18a033bSKonstantin Ananyev                 * use single "/" from request line to preserve pointers,
381e18a033bSKonstantin Ananyev                 * if request line will be copied to large client buffer
382e18a033bSKonstantin Ananyev                 */
383e18a033bSKonstantin Ananyev                r->uri_start = r->schema_end + 1;
384e18a033bSKonstantin Ananyev                r->uri_end = r->schema_end + 2;
385e18a033bSKonstantin Ananyev                state = sw_host_http_09;
386e18a033bSKonstantin Ananyev                break;
387e18a033bSKonstantin Ananyev            default:
388e18a033bSKonstantin Ananyev                return NGX_HTTP_PARSE_INVALID_REQUEST;
389e18a033bSKonstantin Ananyev            }
390e18a033bSKonstantin Ananyev            break;
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyev        case sw_host_ip_literal:
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev            if (ch >= '0' && ch <= '9') {
395e18a033bSKonstantin Ananyev                break;
396e18a033bSKonstantin Ananyev            }
397e18a033bSKonstantin Ananyev
398e18a033bSKonstantin Ananyev            c = (u_char) (ch | 0x20);
399e18a033bSKonstantin Ananyev            if (c >= 'a' && c <= 'z') {
400e18a033bSKonstantin Ananyev                break;
401e18a033bSKonstantin Ananyev            }
402e18a033bSKonstantin Ananyev
403e18a033bSKonstantin Ananyev            switch (ch) {
404e18a033bSKonstantin Ananyev            case ':':
405e18a033bSKonstantin Ananyev                break;
406e18a033bSKonstantin Ananyev            case ']':
407e18a033bSKonstantin Ananyev                state = sw_host_end;
408e18a033bSKonstantin Ananyev                break;
409e18a033bSKonstantin Ananyev            case '-':
410e18a033bSKonstantin Ananyev            case '.':
411e18a033bSKonstantin Ananyev            case '_':
412e18a033bSKonstantin Ananyev            case '~':
413e18a033bSKonstantin Ananyev                /* unreserved */
414e18a033bSKonstantin Ananyev                break;
415e18a033bSKonstantin Ananyev            case '!':
416e18a033bSKonstantin Ananyev            case '$':
417e18a033bSKonstantin Ananyev            case '&':
418e18a033bSKonstantin Ananyev            case '\'':
419