kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit fe43ed09aceedb380ae663cc31b0af7c1dfd924c
parent db31f37ab01030e9233ce1c981b763a0c035727d
Author: Frederic Cambus <fred@statdns.com>
Date:   Tue,  3 Mar 2020 12:53:18 +0100

Add the http_pretty_error configuration option.

When enabled, Kore returns HTML error pages for status codes 4xx and
5xx instead of empty content.

Diffstat:
include/kore/http.h | 1+
src/config.c | 17+++++++++++++++++
src/http.c | 37++++++++++++++++++++++++++++++++++++-
3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/include/kore/http.h b/include/kore/http.h @@ -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; diff --git a/src/config.c b/src/config.c @@ -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 @@ -1335,6 +1337,21 @@ configure_http_server_version(char *version) } 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) { int err; diff --git a/src/http.c b/src/http.c @@ -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; +}