📄 ngx_http_parse.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>static uint32_t usual[] = { 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */#if (NGX_WIN32) 0xefffffff, /* 1110 1111 1111 1111 1111 1111 1111 1111 */#else 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */#endif /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */};#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)#define ngx_str3_cmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)#define ngx_str3Ocmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)#define ngx_str4cmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && m[4] == c4#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4)#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4) \ && m[8] == c8#else /* !(NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) */#define ngx_str3_cmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[1] == c1 && m[2] == c2#define ngx_str3Ocmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[2] == c2 && m[3] == c3#define ngx_str4cmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3#define ngx_str5cmp(m, c0, c1, c2, c3, c4) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4#define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5#define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6#define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7#define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8#endif/* gcc, icc, msvc and others compile these switches as an jump table */ngx_int_tngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b){ u_char c, ch, *p, *m; enum { sw_start = 0, sw_method, sw_spaces_before_uri, sw_schema, sw_schema_slash, sw_schema_slash_slash, sw_host, sw_port, sw_after_slash_in_uri, sw_check_uri, sw_uri, sw_http_09, sw_http_H, sw_http_HT, sw_http_HTT, sw_http_HTTP, sw_first_major_digit, sw_major_digit, sw_first_minor_digit, sw_minor_digit, sw_spaces_after_digit, sw_almost_done } state; state = r->state; for (p = b->pos; p < b->last; p++) { ch = *p; switch (state) { /* HTTP methods: GET, HEAD, POST */ case sw_start: r->request_start = p; if (ch == CR || ch == LF) { break; } if (ch < 'A' || ch > 'Z') { return NGX_HTTP_PARSE_INVALID_METHOD; } state = sw_method; break; case sw_method: if (ch == ' ') { r->method_end = p - 1; m = r->request_start; switch (p - m) { case 3: if (ngx_str3_cmp(m, 'G', 'E', 'T', ' ')) { r->method = NGX_HTTP_GET; break; } if (ngx_str3_cmp(m, 'P', 'U', 'T', ' ')) { r->method = NGX_HTTP_PUT; break; } break; case 4: if (m[1] == 'O') { if (ngx_str3Ocmp(m, 'P', 'O', 'S', 'T')) { r->method = NGX_HTTP_POST; break; } if (ngx_str3Ocmp(m, 'C', 'O', 'P', 'Y')) { r->method = NGX_HTTP_COPY; break; } if (ngx_str3Ocmp(m, 'M', 'O', 'V', 'E')) { r->method = NGX_HTTP_MOVE; break; } if (ngx_str3Ocmp(m, 'L', 'O', 'C', 'K')) { r->method = NGX_HTTP_LOCK; break; } } else { if (ngx_str4cmp(m, 'H', 'E', 'A', 'D')) { r->method = NGX_HTTP_HEAD; break; } } break; case 5: if (ngx_str5cmp(m, 'M', 'K', 'C', 'O', 'L')) { r->method = NGX_HTTP_MKCOL; } if (ngx_str5cmp(m, 'T', 'R', 'A', 'C', 'E')) { r->method = NGX_HTTP_TRACE; } break; case 6: if (ngx_str6cmp(m, 'D', 'E', 'L', 'E', 'T', 'E')) { r->method = NGX_HTTP_DELETE; break; } if (ngx_str6cmp(m, 'U', 'N', 'L', 'O', 'C', 'K')) { r->method = NGX_HTTP_UNLOCK; break; } break; case 7: if (ngx_str7_cmp(m, 'O', 'P', 'T', 'I', 'O', 'N', 'S', ' ')) { r->method = NGX_HTTP_OPTIONS; } break; case 8: if (ngx_str8cmp(m, 'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D')) { r->method = NGX_HTTP_PROPFIND; } break; case 9: if (ngx_str9cmp(m, 'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H')) { r->method = NGX_HTTP_PROPPATCH; } break; } state = sw_spaces_before_uri; break; } if (ch < 'A' || ch > 'Z') { return NGX_HTTP_PARSE_INVALID_METHOD; } break; /* space* before URI */ case sw_spaces_before_uri: if (ch == '/' ){ r->uri_start = p; state = sw_after_slash_in_uri; break; } c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { r->schema_start = p; state = sw_schema; break; } switch (ch) { case ' ': break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_schema: c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { break; } switch (ch) { case ':': r->schema_end = p; state = sw_schema_slash; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_schema_slash: switch (ch) { case '/': state = sw_schema_slash_slash; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_schema_slash_slash: switch (ch) { case '/': r->host_start = p + 1; state = sw_host; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_host: c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { break; } if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') { break; } r->host_end = p; switch (ch) { case ':': state = sw_port; break; case '/': r->uri_start = p; state = sw_after_slash_in_uri; break; case ' ': /* * use single "/" from request line to preserve pointers, * if request line will be copied to large client buffer */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_port: if (ch >= '0' && ch <= '9') { break; } switch (ch) { case '/': r->port_end = p; r->uri_start = p; state = sw_after_slash_in_uri; break; case ' ': r->port_end = p; /* * use single "/" from request line to preserve pointers, * if request line will be copied to large client buffer */ r->uri_start = r->schema_end + 1; r->uri_end = r->schema_end + 2; state = sw_http_09; break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } break; /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: if (usual[ch >> 5] & (1 << (ch & 0x1f))) { state = sw_check_uri; break; } switch (ch) { case ' ': r->uri_end = p; state = sw_http_09; break; case CR: r->uri_end = p; r->http_minor = 9; state = sw_almost_done; break; case LF: r->uri_end = p; r->http_minor = 9; goto done; case '.': r->complex_uri = 1; state = sw_uri; break; case '%': r->quoted_uri = 1; state = sw_uri; break; case '/': r->complex_uri = 1; state = sw_uri; break;#if (NGX_WIN32) case '\\': r->complex_uri = 1; state = sw_uri; break;#endif case '?': r->args_start = p + 1; state = sw_uri; break; case '#': r->complex_uri = 1; state = sw_uri; break; case '+': r->plus_in_uri = 1; break; case '\0': r->zero_in_uri = 1; break; default: state = sw_check_uri; break; } break; /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: if (usual[ch >> 5] & (1 << (ch & 0x1f))) { break; } switch (ch) { case '/': r->uri_ext = NULL; state = sw_after_slash_in_uri; break; case '.': r->uri_ext = p + 1; break; case ' ': r->uri_end = p; state = sw_http_09; break; case CR: r->uri_end = p; r->http_minor = 9; state = sw_almost_done; break; case LF: r->uri_end = p; r->http_minor = 9; goto done;#if (NGX_WIN32) case '\\': r->complex_uri = 1; state = sw_after_slash_in_uri; break;#endif case '%': r->quoted_uri = 1; state = sw_uri; break; case '?': r->args_start = p + 1; state = sw_uri; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -