From b5ba2b0177c0964a39500bc6bbf8f467a8401b14 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 11 Jun 2019 16:08:25 +0200 Subject: [PATCH] MINOR: http: turn default error files to HTTP/1.1 For quite a long time we've been saying that the default error files should produce HTTP/1.1 responses and since it's of low importance, it always gets forgotten. So here it finally comes. Each status code now properly contains a content-length header so that the output is clean and doesn't force upstream proxies to switch to chunked encoding or to close the connection immediately after the response, which is particularly annoying for 401 or 407 for example. It's worth noting that the 3xx codes had already been turned to HTTP/1.1. This patch will obviously not change anything for user-provided error files. --- src/http.c | 42 ++++++++++++++++++++++++++++-------------- src/proto_htx.c | 3 ++- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/http.c b/src/http.c index 7c3f6bbcf..66a4282f4 100644 --- a/src/http.c +++ b/src/http.c @@ -198,7 +198,8 @@ const char *HTTP_308 = /* 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" + "HTTP/1.1 401 Unauthorized\r\n" + "Content-length: 112\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -207,7 +208,8 @@ const char *HTTP_401_fmt = "

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" + "HTTP/1.1 407 Unauthorized\r\n" + "Content-length: 112\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -232,7 +234,8 @@ const int http_err_codes[HTTP_ERR_SIZE] = { const char *http_err_msgs[HTTP_ERR_SIZE] = { [HTTP_ERR_200] = - "HTTP/1.0 200 OK\r\n" + "HTTP/1.1 200 OK\r\n" + "Content-length: 58\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -240,7 +243,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

200 OK

\nService ready.\n\n", [HTTP_ERR_400] = - "HTTP/1.0 400 Bad request\r\n" + "HTTP/1.1 400 Bad request\r\n" + "Content-length: 90\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -248,7 +252,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

400 Bad request

\nYour browser sent an invalid request.\n\n", [HTTP_ERR_403] = - "HTTP/1.0 403 Forbidden\r\n" + "HTTP/1.1 403 Forbidden\r\n" + "Content-length: 93\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -256,7 +261,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

403 Forbidden

\nRequest forbidden by administrative rules.\n\n", [HTTP_ERR_405] = - "HTTP/1.0 405 Method Not Allowed\r\n" + "HTTP/1.1 405 Method Not Allowed\r\n" + "Content-length: 146\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -264,7 +270,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

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" + "HTTP/1.1 408 Request Time-out\r\n" + "Content-length: 110\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -272,7 +279,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

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" + "HTTP/1.1 421 Misdirected Request\r\n" + "Content-length: 104\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -280,7 +288,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

421 Misdirected Request

\nRequest sent to a non-authoritative server.\n\n", [HTTP_ERR_425] = - "HTTP/1.0 425 Too Early\r\n" + "HTTP/1.1 425 Too Early\r\n" + "Content-length: 80\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -288,7 +297,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

425 Too Early

\nYour browser sent early data.\n\n", [HTTP_ERR_429] = - "HTTP/1.0 429 Too Many Requests\r\n" + "HTTP/1.1 429 Too Many Requests\r\n" + "Content-length: 117\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -296,7 +306,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

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" + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-length: 96\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -304,7 +315,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

500 Internal Server Error

\nAn internal server error occured.\n\n", [HTTP_ERR_502] = - "HTTP/1.0 502 Bad Gateway\r\n" + "HTTP/1.1 502 Bad Gateway\r\n" + "Content-length: 107\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -312,7 +324,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

502 Bad Gateway

\nThe server returned an invalid or incomplete response.\n\n", [HTTP_ERR_503] = - "HTTP/1.0 503 Service Unavailable\r\n" + "HTTP/1.1 503 Service Unavailable\r\n" + "Content-length: 107\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -320,7 +333,8 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { "

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" + "HTTP/1.1 504 Gateway Time-out\r\n" + "Content-length: 92\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" diff --git a/src/proto_htx.c b/src/proto_htx.c index f52714b27..7a1f9c516 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -5496,7 +5496,8 @@ static int htx_reply_40x_unauthorized(struct stream *s, const char *auth_realm) if (chunk_printf(&trash, "Basic realm=\"%s\"", auth_realm) == -1) goto fail; - if (!htx_add_header(htx, ist("Cache-Control"), ist("no-cache")) || + if (!htx_add_header(htx, ist("Content-length"), ist("112")) || + !htx_add_header(htx, ist("Cache-Control"), ist("no-cache")) || !htx_add_header(htx, ist("Connection"), ist("close")) || !htx_add_header(htx, ist("Content-Type"), ist("text/html"))) goto fail;