mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-25 06:53:03 +00:00
186 lines
5.5 KiB
C
186 lines
5.5 KiB
C
|
/*
|
||
|
* HTTP semantics
|
||
|
*
|
||
|
* Copyright 2000-2018 Willy Tarreau <w@1wt.eu>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* as published by the Free Software Foundation; either version
|
||
|
* 2 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <common/config.h>
|
||
|
#include <common/http.h>
|
||
|
|
||
|
/* It is about twice as fast on recent architectures to lookup a byte in a
|
||
|
* table than to perform a boolean AND or OR between two tests. Refer to
|
||
|
* RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
|
||
|
* neither a separator nor a CTL char. An http ver_token is any ASCII which can
|
||
|
* be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
|
||
|
* digit. Note: please do not overwrite values in assignment since gcc-2.95
|
||
|
* will not handle them correctly. It's worth noting that chars 128..255 are
|
||
|
* nothing, not even control chars.
|
||
|
*/
|
||
|
const unsigned char http_char_classes[256] = {
|
||
|
[ 0] = HTTP_FLG_CTL,
|
||
|
[ 1] = HTTP_FLG_CTL,
|
||
|
[ 2] = HTTP_FLG_CTL,
|
||
|
[ 3] = HTTP_FLG_CTL,
|
||
|
[ 4] = HTTP_FLG_CTL,
|
||
|
[ 5] = HTTP_FLG_CTL,
|
||
|
[ 6] = HTTP_FLG_CTL,
|
||
|
[ 7] = HTTP_FLG_CTL,
|
||
|
[ 8] = HTTP_FLG_CTL,
|
||
|
[ 9] = HTTP_FLG_SPHT | HTTP_FLG_LWS | HTTP_FLG_SEP | HTTP_FLG_CTL,
|
||
|
[ 10] = HTTP_FLG_CRLF | HTTP_FLG_LWS | HTTP_FLG_CTL,
|
||
|
[ 11] = HTTP_FLG_CTL,
|
||
|
[ 12] = HTTP_FLG_CTL,
|
||
|
[ 13] = HTTP_FLG_CRLF | HTTP_FLG_LWS | HTTP_FLG_CTL,
|
||
|
[ 14] = HTTP_FLG_CTL,
|
||
|
[ 15] = HTTP_FLG_CTL,
|
||
|
[ 16] = HTTP_FLG_CTL,
|
||
|
[ 17] = HTTP_FLG_CTL,
|
||
|
[ 18] = HTTP_FLG_CTL,
|
||
|
[ 19] = HTTP_FLG_CTL,
|
||
|
[ 20] = HTTP_FLG_CTL,
|
||
|
[ 21] = HTTP_FLG_CTL,
|
||
|
[ 22] = HTTP_FLG_CTL,
|
||
|
[ 23] = HTTP_FLG_CTL,
|
||
|
[ 24] = HTTP_FLG_CTL,
|
||
|
[ 25] = HTTP_FLG_CTL,
|
||
|
[ 26] = HTTP_FLG_CTL,
|
||
|
[ 27] = HTTP_FLG_CTL,
|
||
|
[ 28] = HTTP_FLG_CTL,
|
||
|
[ 29] = HTTP_FLG_CTL,
|
||
|
[ 30] = HTTP_FLG_CTL,
|
||
|
[ 31] = HTTP_FLG_CTL,
|
||
|
[' '] = HTTP_FLG_SPHT | HTTP_FLG_LWS | HTTP_FLG_SEP,
|
||
|
['!'] = HTTP_FLG_TOK,
|
||
|
['"'] = HTTP_FLG_SEP,
|
||
|
['#'] = HTTP_FLG_TOK,
|
||
|
['$'] = HTTP_FLG_TOK,
|
||
|
['%'] = HTTP_FLG_TOK,
|
||
|
['&'] = HTTP_FLG_TOK,
|
||
|
[ 39] = HTTP_FLG_TOK,
|
||
|
['('] = HTTP_FLG_SEP,
|
||
|
[')'] = HTTP_FLG_SEP,
|
||
|
['*'] = HTTP_FLG_TOK,
|
||
|
['+'] = HTTP_FLG_TOK,
|
||
|
[','] = HTTP_FLG_SEP,
|
||
|
['-'] = HTTP_FLG_TOK,
|
||
|
['.'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['/'] = HTTP_FLG_SEP | HTTP_FLG_VER,
|
||
|
['0'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['1'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['2'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['3'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['4'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['5'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['6'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['7'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['8'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
['9'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
|
||
|
[':'] = HTTP_FLG_SEP,
|
||
|
[';'] = HTTP_FLG_SEP,
|
||
|
['<'] = HTTP_FLG_SEP,
|
||
|
['='] = HTTP_FLG_SEP,
|
||
|
['>'] = HTTP_FLG_SEP,
|
||
|
['?'] = HTTP_FLG_SEP,
|
||
|
['@'] = HTTP_FLG_SEP,
|
||
|
['A'] = HTTP_FLG_TOK,
|
||
|
['B'] = HTTP_FLG_TOK,
|
||
|
['C'] = HTTP_FLG_TOK,
|
||
|
['D'] = HTTP_FLG_TOK,
|
||
|
['E'] = HTTP_FLG_TOK,
|
||
|
['F'] = HTTP_FLG_TOK,
|
||
|
['G'] = HTTP_FLG_TOK,
|
||
|
['H'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['I'] = HTTP_FLG_TOK,
|
||
|
['J'] = HTTP_FLG_TOK,
|
||
|
['K'] = HTTP_FLG_TOK,
|
||
|
['L'] = HTTP_FLG_TOK,
|
||
|
['M'] = HTTP_FLG_TOK,
|
||
|
['N'] = HTTP_FLG_TOK,
|
||
|
['O'] = HTTP_FLG_TOK,
|
||
|
['P'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['Q'] = HTTP_FLG_TOK,
|
||
|
['R'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['S'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['T'] = HTTP_FLG_TOK | HTTP_FLG_VER,
|
||
|
['U'] = HTTP_FLG_TOK,
|
||
|
['V'] = HTTP_FLG_TOK,
|
||
|
['W'] = HTTP_FLG_TOK,
|
||
|
['X'] = HTTP_FLG_TOK,
|
||
|
['Y'] = HTTP_FLG_TOK,
|
||
|
['Z'] = HTTP_FLG_TOK,
|
||
|
['['] = HTTP_FLG_SEP,
|
||
|
[ 92] = HTTP_FLG_SEP,
|
||
|
[']'] = HTTP_FLG_SEP,
|
||
|
['^'] = HTTP_FLG_TOK,
|
||
|
['_'] = HTTP_FLG_TOK,
|
||
|
['`'] = HTTP_FLG_TOK,
|
||
|
['a'] = HTTP_FLG_TOK,
|
||
|
['b'] = HTTP_FLG_TOK,
|
||
|
['c'] = HTTP_FLG_TOK,
|
||
|
['d'] = HTTP_FLG_TOK,
|
||
|
['e'] = HTTP_FLG_TOK,
|
||
|
['f'] = HTTP_FLG_TOK,
|
||
|
['g'] = HTTP_FLG_TOK,
|
||
|
['h'] = HTTP_FLG_TOK,
|
||
|
['i'] = HTTP_FLG_TOK,
|
||
|
['j'] = HTTP_FLG_TOK,
|
||
|
['k'] = HTTP_FLG_TOK,
|
||
|
['l'] = HTTP_FLG_TOK,
|
||
|
['m'] = HTTP_FLG_TOK,
|
||
|
['n'] = HTTP_FLG_TOK,
|
||
|
['o'] = HTTP_FLG_TOK,
|
||
|
['p'] = HTTP_FLG_TOK,
|
||
|
['q'] = HTTP_FLG_TOK,
|
||
|
['r'] = HTTP_FLG_TOK,
|
||
|
['s'] = HTTP_FLG_TOK,
|
||
|
['t'] = HTTP_FLG_TOK,
|
||
|
['u'] = HTTP_FLG_TOK,
|
||
|
['v'] = HTTP_FLG_TOK,
|
||
|
['w'] = HTTP_FLG_TOK,
|
||
|
['x'] = HTTP_FLG_TOK,
|
||
|
['y'] = HTTP_FLG_TOK,
|
||
|
['z'] = HTTP_FLG_TOK,
|
||
|
['{'] = HTTP_FLG_SEP,
|
||
|
['|'] = HTTP_FLG_TOK,
|
||
|
['}'] = HTTP_FLG_SEP,
|
||
|
['~'] = HTTP_FLG_TOK,
|
||
|
[127] = HTTP_FLG_CTL,
|
||
|
};
|
||
|
|
||
|
const struct ist http_known_methods[HTTP_METH_OTHER] = {
|
||
|
[HTTP_METH_OPTIONS] = IST("OPTIONS"),
|
||
|
[HTTP_METH_GET] = IST("GET"),
|
||
|
[HTTP_METH_HEAD] = IST("HEAD"),
|
||
|
[HTTP_METH_POST] = IST("POST"),
|
||
|
[HTTP_METH_PUT] = IST("PUT"),
|
||
|
[HTTP_METH_DELETE] = IST("DELETE"),
|
||
|
[HTTP_METH_TRACE] = IST("TRACE"),
|
||
|
[HTTP_METH_CONNECT] = IST("CONNECT"),
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* returns a known method among HTTP_METH_* or HTTP_METH_OTHER for all unknown
|
||
|
* ones.
|
||
|
*/
|
||
|
enum http_meth_t find_http_meth(const char *str, const int len)
|
||
|
{
|
||
|
const struct ist m = ist2(str, len);
|
||
|
|
||
|
if (isteq(m, ist("GET"))) return HTTP_METH_GET;
|
||
|
else if (isteq(m, ist("HEAD"))) return HTTP_METH_HEAD;
|
||
|
else if (isteq(m, ist("POST"))) return HTTP_METH_POST;
|
||
|
else if (isteq(m, ist("CONNECT"))) return HTTP_METH_CONNECT;
|
||
|
else if (isteq(m, ist("PUT"))) return HTTP_METH_PUT;
|
||
|
else if (isteq(m, ist("OPTIONS"))) return HTTP_METH_OPTIONS;
|
||
|
else if (isteq(m, ist("DELETE"))) return HTTP_METH_DELETE;
|
||
|
else if (isteq(m, ist("TRACE"))) return HTTP_METH_TRACE;
|
||
|
else return HTTP_METH_OTHER;
|
||
|
}
|