diff --git a/include/common/http.h b/include/common/http.h index 4184a47f9..90d914ad1 100644 --- a/include/common/http.h +++ b/include/common/http.h @@ -110,10 +110,20 @@ extern const int http_err_codes[HTTP_ERR_SIZE]; extern struct buffer http_err_chunks[HTTP_ERR_SIZE]; const struct ist http_known_methods[HTTP_METH_OTHER]; extern const uint8_t http_char_classes[256]; + +const struct ist HTTP_100; +extern const char *HTTP_301; extern const char *HTTP_302; extern const char *HTTP_303; +extern const char *HTTP_307; +extern const char *HTTP_308; +extern const char *HTTP_401_fmt; +extern const char *HTTP_407_fmt; +int init_http(char **err); enum http_meth_t find_http_meth(const char *str, const int len); +const int http_get_status_idx(unsigned int status); +const char *http_get_reason(unsigned int status); struct ist http_get_path(const struct ist uri); #endif /* _COMMON_HTTP_H */ diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index 9eba1448d..1b8da0661 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -101,7 +101,6 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle struct hdr_idx *idx, int occ, struct hdr_ctx *ctx, char **vptr, size_t *vlen); char *http_txn_get_path(const struct http_txn *txn); -const char *get_reason(unsigned int status); struct http_txn *http_alloc_txn(struct stream *s); void http_init_txn(struct stream *s); diff --git a/src/haproxy.c b/src/haproxy.c index b99334148..d59635629 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1447,6 +1447,11 @@ static void init(int argc, char **argv) init_connection(); /* warning, we init buffers later */ init_pendconn(); + if (!init_http(&err_msg)) { + ha_alert("%s. Aborting.\n", err_msg); + free(err_msg); + abort(); + } init_proto_http(); /* Initialise lua. */ diff --git a/src/hlua.c b/src/hlua.c index 6f001d54d..759e7b21e 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -154,8 +154,6 @@ static int hlua_panic_ljmp(lua_State *L) { longjmp(safe_ljmp_env, 1); } #define APPLET_LAST_CHK 0x10 /* Last chunk sent. */ #define APPLET_HTTP11 0x20 /* Last chunk sent. */ -#define HTTP_100C "HTTP/1.1 100 Continue\r\n\r\n" - /* The main Lua execution context. */ struct hlua gL; @@ -4121,7 +4119,7 @@ __LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_K /* Maybe we cant send a 100-continue ? */ if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) { - ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C)); + ret = ci_putblk(chn, HTTP_100.ptr, HTTP_100.len); /* if ret == -2 or -3 the channel closed or the message si too * big for the buffers. We cant send anything. So, we ignoring * the error, considers that the 100-continue is sent, and try @@ -4207,7 +4205,7 @@ __LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KCon /* Maybe we cant send a 100-continue ? */ if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_100C) { - ret = ci_putblk(chn, HTTP_100C, strlen(HTTP_100C)); + ret = ci_putblk(chn, HTTP_100.ptr, HTTP_100.len); /* if ret == -2 or -3 the channel closed or the message si too * big for the buffers. We cant send anything. So, we ignoring * the error, considers that the 100-continue is sent, and try @@ -4490,7 +4488,7 @@ __LJMP static int hlua_applet_http_start_response(lua_State *L) const char *reason = appctx->appctx->ctx.hlua_apphttp.reason; if (reason == NULL) - reason = get_reason(appctx->appctx->ctx.hlua_apphttp.status); + reason = http_get_reason(appctx->appctx->ctx.hlua_apphttp.status); /* Use the same http version than the request. */ chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n", diff --git a/src/http.c b/src/http.c index 66a91dba7..202f7a468 100644 --- a/src/http.c +++ b/src/http.c @@ -13,6 +13,7 @@ #include #include #include +#include /* 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 @@ -154,6 +155,178 @@ const unsigned char http_char_classes[256] = { [127] = HTTP_FLG_CTL, }; +/* We must put the messages here since GCC cannot initialize consts depending + * on strlen(). + */ +struct buffer http_err_chunks[HTTP_ERR_SIZE]; + +const struct ist HTTP_100 = IST("HTTP/1.1 100 Continue\r\n\r\n"); + +/* Warning: no "connection" header is provided with the 3xx messages below */ +const char *HTTP_301 = + "HTTP/1.1 301 Moved Permanently\r\n" + "Content-length: 0\r\n" + "Location: "; /* not terminated since it will be concatenated with the URL */ + +const char *HTTP_302 = + "HTTP/1.1 302 Found\r\n" + "Cache-Control: no-cache\r\n" + "Content-length: 0\r\n" + "Location: "; /* not terminated since it will be concatenated with the URL */ + +/* same as 302 except that the browser MUST retry with the GET method */ +const char *HTTP_303 = + "HTTP/1.1 303 See Other\r\n" + "Cache-Control: no-cache\r\n" + "Content-length: 0\r\n" + "Location: "; /* not terminated since it will be concatenated with the URL */ + +/* same as 302 except that the browser MUST retry with the same method */ +const char *HTTP_307 = + "HTTP/1.1 307 Temporary Redirect\r\n" + "Cache-Control: no-cache\r\n" + "Content-length: 0\r\n" + "Location: "; /* not terminated since it will be concatenated with the URL */ + +/* same as 301 except that the browser MUST retry with the same method */ +const char *HTTP_308 = + "HTTP/1.1 308 Permanent Redirect\r\n" + "Content-length: 0\r\n" + "Location: "; /* not terminated since it will be concatenated with the URL */ + +/* Warning: this one is an sprintf() fmt string, with as its only argument */ +const char *HTTP_401_fmt = + "HTTP/1.0 401 Unauthorized\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "WWW-Authenticate: Basic realm=\"%s\"\r\n" + "\r\n" + "

401 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; + +const char *HTTP_407_fmt = + "HTTP/1.0 407 Unauthorized\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "Proxy-Authenticate: Basic realm=\"%s\"\r\n" + "\r\n" + "

407 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; + +const int http_err_codes[HTTP_ERR_SIZE] = { + [HTTP_ERR_200] = 200, /* used by "monitor-uri" */ + [HTTP_ERR_400] = 400, + [HTTP_ERR_403] = 403, + [HTTP_ERR_405] = 405, + [HTTP_ERR_408] = 408, + [HTTP_ERR_421] = 421, + [HTTP_ERR_425] = 425, + [HTTP_ERR_429] = 429, + [HTTP_ERR_500] = 500, + [HTTP_ERR_502] = 502, + [HTTP_ERR_503] = 503, + [HTTP_ERR_504] = 504, +}; + +static const char *http_err_msgs[HTTP_ERR_SIZE] = { + [HTTP_ERR_200] = + "HTTP/1.0 200 OK\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

200 OK

\nService ready.\n\n", + + [HTTP_ERR_400] = + "HTTP/1.0 400 Bad request\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

400 Bad request

\nYour browser sent an invalid request.\n\n", + + [HTTP_ERR_403] = + "HTTP/1.0 403 Forbidden\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

403 Forbidden

\nRequest forbidden by administrative rules.\n\n", + + [HTTP_ERR_405] = + "HTTP/1.0 405 Method Not Allowed\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

405 Method Not Allowed

\nA request was made of a resource using a request method not supported by that resource\n\n", + + [HTTP_ERR_408] = + "HTTP/1.0 408 Request Time-out\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

408 Request Time-out

\nYour browser didn't send a complete request in time.\n\n", + + [HTTP_ERR_421] = + "HTTP/1.0 421 Misdirected Request\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

421 Misdirected Request

\nRequest sent to a non-authoritative server.\n\n", + + [HTTP_ERR_425] = + "HTTP/1.0 425 Too Early\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

425 Too Early

\nYour browser sent early data.\n\n", + + [HTTP_ERR_429] = + "HTTP/1.0 429 Too Many Requests\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

429 Too Many Requests

\nYou have sent too many requests in a given amount of time.\n\n", + + [HTTP_ERR_500] = + "HTTP/1.0 500 Internal Server Error\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

500 Internal Server Error

\nAn internal server error occured.\n\n", + + [HTTP_ERR_502] = + "HTTP/1.0 502 Bad Gateway\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

502 Bad Gateway

\nThe server returned an invalid or incomplete response.\n\n", + + [HTTP_ERR_503] = + "HTTP/1.0 503 Service Unavailable\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

503 Service Unavailable

\nNo server is available to handle this request.\n\n", + + [HTTP_ERR_504] = + "HTTP/1.0 504 Gateway Time-out\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

504 Gateway Time-out

\nThe server didn't respond in time.\n\n", + +}; + const struct ist http_known_methods[HTTP_METH_OTHER] = { [HTTP_METH_OPTIONS] = IST("OPTIONS"), [HTTP_METH_GET] = IST("GET"), @@ -184,6 +357,114 @@ enum http_meth_t find_http_meth(const char *str, const int len) else return HTTP_METH_OTHER; } +/* This function returns HTTP_ERR_ (enum) matching http status code. + * Returned value should match codes from http_err_codes. + */ +const int http_get_status_idx(unsigned int status) +{ + switch (status) { + case 200: return HTTP_ERR_200; + case 400: return HTTP_ERR_400; + case 403: return HTTP_ERR_403; + case 405: return HTTP_ERR_405; + case 408: return HTTP_ERR_408; + case 421: return HTTP_ERR_421; + case 425: return HTTP_ERR_425; + case 429: return HTTP_ERR_429; + case 500: return HTTP_ERR_500; + case 502: return HTTP_ERR_502; + case 503: return HTTP_ERR_503; + case 504: return HTTP_ERR_504; + default: return HTTP_ERR_500; + } +} + +/* This function returns a reason associated with the HTTP status. + * This function never fails, a message is always returned. + */ +const char *http_get_reason(unsigned int status) +{ + switch (status) { + case 100: return "Continue"; + case 101: return "Switching Protocols"; + case 102: return "Processing"; + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 207: return "Multi-Status"; + case 210: return "Content Different"; + case 226: return "IM Used"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Moved Temporarily"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 305: return "Use Proxy"; + case 307: return "Temporary Redirect"; + case 308: return "Permanent Redirect"; + case 310: return "Too many Redirects"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Time-out"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Request Entity Too Large"; + case 414: return "Request-URI Too Long"; + case 415: return "Unsupported Media Type"; + case 416: return "Requested range unsatisfiable"; + case 417: return "Expectation failed"; + case 418: return "I'm a teapot"; + case 421: return "Misdirected Request"; + case 422: return "Unprocessable entity"; + case 423: return "Locked"; + case 424: return "Method failure"; + case 425: return "Too Early"; + case 426: return "Upgrade Required"; + case 428: return "Precondition Required"; + case 429: return "Too Many Requests"; + case 431: return "Request Header Fields Too Large"; + case 449: return "Retry With"; + case 450: return "Blocked by Windows Parental Controls"; + case 451: return "Unavailable For Legal Reasons"; + case 456: return "Unrecoverable Error"; + case 499: return "client has closed connection"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway or Proxy Error"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Time-out"; + case 505: return "HTTP Version not supported"; + case 506: return "Variant also negociate"; + case 507: return "Insufficient storage"; + case 508: return "Loop detected"; + case 509: return "Bandwidth Limit Exceeded"; + case 510: return "Not extended"; + case 511: return "Network authentication required"; + case 520: return "Web server is returning an unknown error"; + default: + switch (status) { + case 100 ... 199: return "Informational"; + case 200 ... 299: return "Success"; + case 300 ... 399: return "Redirection"; + case 400 ... 499: return "Client Error"; + case 500 ... 599: return "Server Error"; + default: return "Other"; + } + } +} + /* Parse the URI from the given transaction (which is assumed to be in request * phase) and look for the "/" beginning the PATH. If not found, ist2(0,0) is * returned. Otherwise the pointer and length are returned. @@ -233,3 +514,22 @@ struct ist http_get_path(const struct ist uri) not_found: return ist2(NULL, 0); } + +/* post-initializes the HTTP parts. Returns non-zero on error, with + * pointing to the error message. + */ +int init_http(char **err) +{ + int msg; + + for (msg = 0; msg < HTTP_ERR_SIZE; msg++) { + if (!http_err_msgs[msg]) { + memprintf(err, "Internal error: no message defined for HTTP return code %d", msg); + return 0; + } + + http_err_chunks[msg].area = (char *)http_err_msgs[msg]; + http_err_chunks[msg].data = strlen(http_err_msgs[msg]); + } + return 1; +} diff --git a/src/proto_http.c b/src/proto_http.c index 047e270df..8e899527b 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -76,181 +76,6 @@ #include #include -const char HTTP_100[] = - "HTTP/1.1 100 Continue\r\n\r\n"; - -const struct buffer http_100_chunk = { - .area = (char *)&HTTP_100, - .data = sizeof(HTTP_100)-1 -}; - -/* Warning: no "connection" header is provided with the 3xx messages below */ -const char *HTTP_301 = - "HTTP/1.1 301 Moved Permanently\r\n" - "Content-length: 0\r\n" - "Location: "; /* not terminated since it will be concatenated with the URL */ - -const char *HTTP_302 = - "HTTP/1.1 302 Found\r\n" - "Cache-Control: no-cache\r\n" - "Content-length: 0\r\n" - "Location: "; /* not terminated since it will be concatenated with the URL */ - -/* same as 302 except that the browser MUST retry with the GET method */ -const char *HTTP_303 = - "HTTP/1.1 303 See Other\r\n" - "Cache-Control: no-cache\r\n" - "Content-length: 0\r\n" - "Location: "; /* not terminated since it will be concatenated with the URL */ - - -/* same as 302 except that the browser MUST retry with the same method */ -const char *HTTP_307 = - "HTTP/1.1 307 Temporary Redirect\r\n" - "Cache-Control: no-cache\r\n" - "Content-length: 0\r\n" - "Location: "; /* not terminated since it will be concatenated with the URL */ - -/* same as 301 except that the browser MUST retry with the same method */ -const char *HTTP_308 = - "HTTP/1.1 308 Permanent Redirect\r\n" - "Content-length: 0\r\n" - "Location: "; /* not terminated since it will be concatenated with the URL */ - -/* Warning: this one is an sprintf() fmt string, with as its only argument */ -const char *HTTP_401_fmt = - "HTTP/1.0 401 Unauthorized\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "WWW-Authenticate: Basic realm=\"%s\"\r\n" - "\r\n" - "

401 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; - -const char *HTTP_407_fmt = - "HTTP/1.0 407 Unauthorized\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "Proxy-Authenticate: Basic realm=\"%s\"\r\n" - "\r\n" - "

407 Unauthorized

\nYou need a valid user and password to access this content.\n\n"; - - -const int http_err_codes[HTTP_ERR_SIZE] = { - [HTTP_ERR_200] = 200, /* used by "monitor-uri" */ - [HTTP_ERR_400] = 400, - [HTTP_ERR_403] = 403, - [HTTP_ERR_405] = 405, - [HTTP_ERR_408] = 408, - [HTTP_ERR_421] = 421, - [HTTP_ERR_425] = 425, - [HTTP_ERR_429] = 429, - [HTTP_ERR_500] = 500, - [HTTP_ERR_502] = 502, - [HTTP_ERR_503] = 503, - [HTTP_ERR_504] = 504, -}; - -static const char *http_err_msgs[HTTP_ERR_SIZE] = { - [HTTP_ERR_200] = - "HTTP/1.0 200 OK\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

200 OK

\nService ready.\n\n", - - [HTTP_ERR_400] = - "HTTP/1.0 400 Bad request\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

400 Bad request

\nYour browser sent an invalid request.\n\n", - - [HTTP_ERR_403] = - "HTTP/1.0 403 Forbidden\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

403 Forbidden

\nRequest forbidden by administrative rules.\n\n", - - [HTTP_ERR_405] = - "HTTP/1.0 405 Method Not Allowed\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

405 Method Not Allowed

\nA request was made of a resource using a request method not supported by that resource\n\n", - - [HTTP_ERR_408] = - "HTTP/1.0 408 Request Time-out\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

408 Request Time-out

\nYour browser didn't send a complete request in time.\n\n", - - [HTTP_ERR_421] = - "HTTP/1.0 421 Misdirected Request\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

421 Misdirected Request

\nRequest sent to a non-authoritative server.\n\n", - - [HTTP_ERR_425] = - "HTTP/1.0 425 Too Early\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

425 Too Early

\nYour browser sent early data.\n\n", - - [HTTP_ERR_429] = - "HTTP/1.0 429 Too Many Requests\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

429 Too Many Requests

\nYou have sent too many requests in a given amount of time.\n\n", - - [HTTP_ERR_500] = - "HTTP/1.0 500 Internal Server Error\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

500 Internal Server Error

\nAn internal server error occured.\n\n", - - [HTTP_ERR_502] = - "HTTP/1.0 502 Bad Gateway\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

502 Bad Gateway

\nThe server returned an invalid or incomplete response.\n\n", - - [HTTP_ERR_503] = - "HTTP/1.0 503 Service Unavailable\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

503 Service Unavailable

\nNo server is available to handle this request.\n\n", - - [HTTP_ERR_504] = - "HTTP/1.0 504 Gateway Time-out\r\n" - "Cache-Control: no-cache\r\n" - "Connection: close\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "

504 Gateway Time-out

\nThe server didn't respond in time.\n\n", - -}; - /* status codes available for the stats admin page (strictly 4 chars length) */ const char *stat_status_codes[STAT_STATUS_SIZE] = { [STAT_STATUS_DENY] = "DENY", @@ -273,11 +98,6 @@ struct action_kw_list http_res_keywords = { .list = LIST_HEAD_INIT(http_res_keywords.list) }; -/* We must put the messages here since GCC cannot initialize consts depending - * on strlen(). - */ -struct buffer http_err_chunks[HTTP_ERR_SIZE]; - /* this struct is used between calls to smp_fetch_hdr() or smp_fetch_cookie() */ static THREAD_LOCAL struct hdr_ctx static_hdr_ctx; @@ -303,129 +123,10 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s static inline int http_msg_forward_body(struct stream *s, struct http_msg *msg); static inline int http_msg_forward_chunked_body(struct stream *s, struct http_msg *msg); -/* This function returns a reason associated with the HTTP status. - * This function never fails, a message is always returned. - */ -const char *get_reason(unsigned int status) -{ - switch (status) { - case 100: return "Continue"; - case 101: return "Switching Protocols"; - case 102: return "Processing"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 210: return "Content Different"; - case 226: return "IM Used"; - case 300: return "Multiple Choices"; - case 301: return "Moved Permanently"; - case 302: return "Moved Temporarily"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 307: return "Temporary Redirect"; - case 308: return "Permanent Redirect"; - case 310: return "Too many Redirects"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Time-out"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Request Entity Too Large"; - case 414: return "Request-URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Requested range unsatisfiable"; - case 417: return "Expectation failed"; - case 418: return "I'm a teapot"; - case 421: return "Misdirected Request"; - case 422: return "Unprocessable entity"; - case 423: return "Locked"; - case 424: return "Method failure"; - case 425: return "Too Early"; - case 426: return "Upgrade Required"; - case 428: return "Precondition Required"; - case 429: return "Too Many Requests"; - case 431: return "Request Header Fields Too Large"; - case 449: return "Retry With"; - case 450: return "Blocked by Windows Parental Controls"; - case 451: return "Unavailable For Legal Reasons"; - case 456: return "Unrecoverable Error"; - case 499: return "client has closed connection"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway or Proxy Error"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Time-out"; - case 505: return "HTTP Version not supported"; - case 506: return "Variant also negociate"; - case 507: return "Insufficient storage"; - case 508: return "Loop detected"; - case 509: return "Bandwidth Limit Exceeded"; - case 510: return "Not extended"; - case 511: return "Network authentication required"; - case 520: return "Web server is returning an unknown error"; - default: - switch (status) { - case 100 ... 199: return "Informational"; - case 200 ... 299: return "Success"; - case 300 ... 399: return "Redirection"; - case 400 ... 499: return "Client Error"; - case 500 ... 599: return "Server Error"; - default: return "Other"; - } - } -} - -/* This function returns HTTP_ERR_ (enum) matching http status code. - * Returned value should match codes from http_err_codes. - */ -static const int http_get_status_idx(unsigned int status) -{ - switch (status) { - case 200: return HTTP_ERR_200; - case 400: return HTTP_ERR_400; - case 403: return HTTP_ERR_403; - case 405: return HTTP_ERR_405; - case 408: return HTTP_ERR_408; - case 421: return HTTP_ERR_421; - case 425: return HTTP_ERR_425; - case 429: return HTTP_ERR_429; - case 500: return HTTP_ERR_500; - case 502: return HTTP_ERR_502; - case 503: return HTTP_ERR_503; - case 504: return HTTP_ERR_504; - default: return HTTP_ERR_500; - } -} - void init_proto_http() { int i; char *tmp; - int msg; - - for (msg = 0; msg < HTTP_ERR_SIZE; msg++) { - if (!http_err_msgs[msg]) { - ha_alert("Internal error: no message defined for HTTP return code %d. Aborting.\n", msg); - abort(); - } - - http_err_chunks[msg].area = (char *)http_err_msgs[msg]; - http_err_chunks[msg].data = strlen(http_err_msgs[msg]); - } /* initialize the log header encoding map : '{|}"#' should be encoded with * '#' as prefix, as well as non-printable characters ( <32 or >= 127 ). @@ -4004,9 +3705,7 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit /* Expect is allowed in 1.1, look for it */ if (http_find_header2("Expect", 6, ci_head(req), &txn->hdr_idx, &ctx) && unlikely(ctx.vlen == 12 && strncasecmp(ctx.line+ctx.val, "100-continue", 12) == 0)) { - co_inject(&s->res, - http_100_chunk.area, - http_100_chunk.data); + co_inject(&s->res, HTTP_100.ptr, HTTP_100.len); http_remove_header2(&txn->req, &txn->hdr_idx, &ctx); } } @@ -11898,7 +11597,7 @@ void http_set_status(unsigned int status, const char *reason, struct stream *s) /* Do we have a custom reason format string? */ if (msg == NULL) - msg = get_reason(status); + msg = http_get_reason(status); msg_len = strlen(msg); strncpy(&trash.area[trash.data], msg, trash.size - trash.data); trash.data += msg_len;