Add the http_pretty_error configuration option.

When enabled, Kore returns HTML error pages for status codes 4xx and
5xx instead of empty content.
This commit is contained in:
Frederic Cambus 2020-03-03 12:53:18 +01:00 committed by Joris Vink
parent db31f37ab0
commit fe43ed09ac
3 changed files with 54 additions and 1 deletions

View File

@ -327,6 +327,7 @@ extern u_int16_t http_keepalive_time;
extern u_int32_t http_request_limit;
extern u_int32_t http_request_count;
extern u_int64_t http_body_disk_offload;
extern int http_pretty_error;
extern char *http_body_disk_path;
extern struct kore_pool http_header_pool;

View File

@ -130,6 +130,7 @@ static int configure_http_request_limit(char *);
static int configure_http_body_disk_offload(char *);
static int configure_http_body_disk_path(char *);
static int configure_http_server_version(char *);
static int configure_http_pretty_error(char *);
static int configure_validator(char *);
static int configure_params(char *);
static int configure_validate(char *);
@ -258,6 +259,7 @@ static struct {
{ "http_body_disk_offload", configure_http_body_disk_offload },
{ "http_body_disk_path", configure_http_body_disk_path },
{ "http_server_version", configure_http_server_version },
{ "http_pretty_error", configure_http_pretty_error },
{ "websocket_maxframe", configure_websocket_maxframe },
{ "websocket_timeout", configure_websocket_timeout },
#endif
@ -1334,6 +1336,21 @@ configure_http_server_version(char *version)
return (KORE_RESULT_OK);
}
static int
configure_http_pretty_error(char *yesno)
{
if (!strcmp(yesno, "no")) {
http_pretty_error = 0;
} else if (!strcmp(yesno, "yes")) {
http_pretty_error = 1;
} else {
printf("invalid '%s' for yes|no http_pretty_error option\n", yesno);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
static int
configure_http_hsts_enable(char *option)
{

View File

@ -140,6 +140,7 @@ static int multipart_parse_headers(struct http_request *,
static struct http_request *http_request_new(struct connection *,
const char *, const char *, char *,
const char *);
static struct kore_buf *http_pretty_error_page(int);
static struct kore_buf *header_buf;
static struct kore_buf *ckhdr_buf;
@ -168,6 +169,8 @@ size_t http_body_max = HTTP_BODY_MAX_LEN;
char *http_body_disk_path = HTTP_BODY_DISK_PATH;
u_int64_t http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
int http_pretty_error = 0;
void
http_parent_init(void)
{
@ -2077,6 +2080,8 @@ http_response_normal(struct http_request *req, struct connection *c,
const char *conn;
char version;
int connection_close;
int send_body = 1;
u_int8_t *error_page = NULL;
kore_buf_reset(header_buf);
@ -2129,6 +2134,12 @@ http_response_normal(struct http_request *req, struct connection *c,
http_hsts_enable);
}
if (http_pretty_error && d == NULL && status >= 400) {
struct kore_buf *page = http_pretty_error_page(status);
error_page = kore_buf_release(page, &len);
d = error_page;
}
if (req != NULL) {
TAILQ_FOREACH(ck, &(req->resp_cookies), list)
http_write_response_cookie(ck);
@ -2153,7 +2164,10 @@ http_response_normal(struct http_request *req, struct connection *c,
kore_buf_append(header_buf, "\r\n", 2);
net_send_queue(c, header_buf->data, header_buf->offset);
if (d != NULL && req != NULL && req->method != HTTP_METHOD_HEAD)
if (req != NULL && req->method == HTTP_METHOD_HEAD)
send_body = 0;
if (d != NULL && send_body)
net_send_queue(c, d, len);
if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
@ -2161,6 +2175,9 @@ http_response_normal(struct http_request *req, struct connection *c,
if (req != NULL)
req->content_length = len;
if (error_page)
kore_free(error_page);
}
static void
@ -2481,3 +2498,21 @@ http_validate_header(char *header)
return (value);
}
static struct kore_buf *
http_pretty_error_page(int status)
{
const char *error_template =
"<html>\n<head>\n\t<title>%d %s</title>"
"</head>\n<body>\n\t"
"<h1>%d %s</h1>\n"
"</body>\n</html>\n";
const char *status_text = http_status_text(status);
struct kore_buf *r = kore_buf_alloc(128);
kore_buf_appendf(r, error_template,
status, status_text, status, status_text);
return r;
}