mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-25 23:20:45 +00:00
REORG: http: move error codes production and processing to http.c
These error codes and messages are agnostic to the version, even if they are represented as HTTP/1.0 messages. Ultimately they will have to be transformed into internal HTTP messages to be used everywhere. The HTTP/1.1 100 Continue message was turned to an IST and the local copy in the Lua code was removed.
This commit is contained in:
parent
6b952c8101
commit
04f1e2d202
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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",
|
||||
|
300
src/http.c
300
src/http.c
@ -13,6 +13,7 @@
|
||||
#include <ctype.h>
|
||||
#include <common/config.h>
|
||||
#include <common/http.h>
|
||||
#include <common/standard.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
|
||||
@ -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 <realm> 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"
|
||||
"<html><body><h1>401 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\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"
|
||||
"<html><body><h1>407 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\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"
|
||||
"<html><body><h1>200 OK</h1>\nService ready.\n</body></html>\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"
|
||||
"<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request.\n</body></html>\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"
|
||||
"<html><body><h1>403 Forbidden</h1>\nRequest forbidden by administrative rules.\n</body></html>\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"
|
||||
"<html><body><h1>405 Method Not Allowed</h1>\nA request was made of a resource using a request method not supported by that resource\n</body></html>\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"
|
||||
"<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\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"
|
||||
"<html><body><h1>421 Misdirected Request</h1>\nRequest sent to a non-authoritative server.\n</body></html>\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"
|
||||
"<html><body><h1>425 Too Early</h1>\nYour browser sent early data.\n</body></html>\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"
|
||||
"<html><body><h1>429 Too Many Requests</h1>\nYou have sent too many requests in a given amount of time.\n</body></html>\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"
|
||||
"<html><body><h1>500 Internal Server Error</h1>\nAn internal server error occured.\n</body></html>\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"
|
||||
"<html><body><h1>502 Bad Gateway</h1>\nThe server returned an invalid or incomplete response.\n</body></html>\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"
|
||||
"<html><body><h1>503 Service Unavailable</h1>\nNo server is available to handle this request.\n</body></html>\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"
|
||||
"<html><body><h1>504 Gateway Time-out</h1>\nThe server didn't respond in time.\n</body></html>\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_<num> (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 <err>
|
||||
* 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;
|
||||
}
|
||||
|
305
src/proto_http.c
305
src/proto_http.c
@ -76,181 +76,6 @@
|
||||
#include <proto/pattern.h>
|
||||
#include <proto/vars.h>
|
||||
|
||||
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 <realm> 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"
|
||||
"<html><body><h1>401 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\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"
|
||||
"<html><body><h1>407 Unauthorized</h1>\nYou need a valid user and password to access this content.\n</body></html>\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"
|
||||
"<html><body><h1>200 OK</h1>\nService ready.\n</body></html>\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"
|
||||
"<html><body><h1>400 Bad request</h1>\nYour browser sent an invalid request.\n</body></html>\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"
|
||||
"<html><body><h1>403 Forbidden</h1>\nRequest forbidden by administrative rules.\n</body></html>\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"
|
||||
"<html><body><h1>405 Method Not Allowed</h1>\nA request was made of a resource using a request method not supported by that resource\n</body></html>\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"
|
||||
"<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\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"
|
||||
"<html><body><h1>421 Misdirected Request</h1>\nRequest sent to a non-authoritative server.\n</body></html>\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"
|
||||
"<html><body><h1>425 Too Early</h1>\nYour browser sent early data.\n</body></html>\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"
|
||||
"<html><body><h1>429 Too Many Requests</h1>\nYou have sent too many requests in a given amount of time.\n</body></html>\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"
|
||||
"<html><body><h1>500 Internal Server Error</h1>\nAn internal server error occured.\n</body></html>\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"
|
||||
"<html><body><h1>502 Bad Gateway</h1>\nThe server returned an invalid or incomplete response.\n</body></html>\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"
|
||||
"<html><body><h1>503 Service Unavailable</h1>\nNo server is available to handle this request.\n</body></html>\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"
|
||||
"<html><body><h1>504 Gateway Time-out</h1>\nThe server didn't respond in time.\n</body></html>\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_<num> (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;
|
||||
|
Loading…
Reference in New Issue
Block a user