From 123f168a3b5d1e378aa2827d6306a0270b553f90 Mon Sep 17 00:00:00 2001 From: Laslo Hunhold Date: Fri, 28 Aug 2020 22:32:47 +0200 Subject: [PATCH] Replace http_send_status() with http_prepare_error_response() This approach fits better in line of first initializing the response struct and then sending the header with http_send_header() later. Signed-off-by: Laslo Hunhold --- http.c | 70 +++++++++++++++++++++++++++++++--------------------------- http.h | 2 ++ main.c | 20 ++++++++--------- 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/http.c b/http.c index b6b1ab7..5b0390d 100644 --- a/http.c +++ b/http.c @@ -99,42 +99,18 @@ http_send_header(int fd, const struct response *res) esc) < 0) { return S_REQUEST_TIMEOUT; } - } - - return res->status; -} - -enum status -http_send_status(int fd, enum status s) -{ - enum status sendstatus; - - struct response res = { - .status = s, - .field[RES_CONTENT_TYPE] = "text/html; charset=utf-8", - }; - - if (s == S_METHOD_NOT_ALLOWED) { - if (esnprintf(res.field[RES_ALLOW], - sizeof(res.field[RES_ALLOW]), "%s", - "Allow: GET, HEAD")) { - return S_INTERNAL_SERVER_ERROR; + } else if (res->type == RESTYPE_ERROR) { + if (dprintf(fd, + "\n\n\t\n" + "\t\t%d %s\n\t\n\t\n" + "\t\t

%d %s

\n\t\n\n", + res->status, status_str[res->status], + res->status, status_str[res->status]) < 0) { + return S_REQUEST_TIMEOUT; } } - if ((sendstatus = http_send_header(fd, &res)) != s) { - return sendstatus; - } - - if (dprintf(fd, - "\n\n\t\n" - "\t\t%d %s\n\t\n\t\n" - "\t\t

%d %s

\n\t\n\n", - s, status_str[s], s, status_str[s]) < 0) { - return S_REQUEST_TIMEOUT; - } - - return s; + return res->status; } static void @@ -827,3 +803,31 @@ http_prepare_response(const struct request *req, struct response *res, return 0; } + +void +http_prepare_error_response(const struct request *req, + struct response *res, enum status s) +{ + /* used later */ + (void)req; + + /* empty all response fields */ + memset(res, 0, sizeof(*res)); + + res->type = RESTYPE_ERROR; + res->status = s; + + if (esnprintf(res->field[RES_CONTENT_TYPE], + sizeof(res->field[RES_CONTENT_TYPE]), + "text/html; charset=utf-8")) { + res->status = S_INTERNAL_SERVER_ERROR; + } + + if (res->status == S_METHOD_NOT_ALLOWED) { + if (esnprintf(res->field[RES_ALLOW], + sizeof(res->field[RES_ALLOW]), + "Allow: GET, HEAD")) { + res->status = S_INTERNAL_SERVER_ERROR; + } + } +} diff --git a/http.h b/http.h index a9cf871..caac765 100644 --- a/http.h +++ b/http.h @@ -105,5 +105,7 @@ enum status http_recv_header(int, char *, size_t, size_t *); enum status http_parse_header(const char *, struct request *); enum status http_prepare_response(const struct request *, struct response *, const struct server *); +void http_prepare_error_response(const struct request *, + struct response *, enum status); #endif /* HTTP_H */ diff --git a/main.c b/main.c index 110af1a..fa0fa0f 100644 --- a/main.c +++ b/main.c @@ -41,16 +41,16 @@ serve(int infd, const struct sockaddr_storage *in_sa, const struct server *srv) if ((status = http_recv_header(c.fd, c.header, LEN(c.header), &c.off)) || (status = http_parse_header(c.header, &c.req)) || (status = http_prepare_response(&c.req, &c.res, srv))) { - status = http_send_status(c.fd, status); - } else { - status = http_send_header(c.fd, &c.res); + http_prepare_error_response(&c.req, &c.res, status); + } - /* send data */ - if (c.res.type == RESTYPE_FILE) { - resp_file(c.fd, &c.res); - } else if (c.res.type == RESTYPE_DIRLISTING) { - resp_dir(c.fd, &c.res); - } + status = http_send_header(c.fd, &c.res); + + /* send data */ + if (c.res.type == RESTYPE_FILE) { + resp_file(c.fd, &c.res); + } else if (c.res.type == RESTYPE_DIRLISTING) { + resp_dir(c.fd, &c.res); } /* write output to log */ @@ -63,7 +63,7 @@ serve(int infd, const struct sockaddr_storage *in_sa, const struct server *srv) if (sock_get_inaddr_str(in_sa, inaddr, LEN(inaddr))) { goto cleanup; } - printf("%s\t%s\t%d\t%s\t%s\n", tstmp, inaddr, status, + printf("%s\t%s\t%d\t%s\t%s\n", tstmp, inaddr, c.res.status, c.req.field[REQ_HOST], c.req.uri); cleanup: /* clean up and finish */