Replace http_send_status() with http_prepare_error_response() - quark - quark web server
 (HTM) git clone git://git.suckless.org/quark
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 123f168a3b5d1e378aa2827d6306a0270b553f90
 (DIR) parent 601b56d27095e4340e5afcf3385465a1f7f96d98
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Fri, 28 Aug 2020 22:32:47 +0200
       
       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 <dev@frign.de>
       
       Diffstat:
         M http.c                              |      70 ++++++++++++++++---------------
         M http.h                              |       2 ++
         M main.c                              |      22 +++++++++++-----------
       
       3 files changed, 50 insertions(+), 44 deletions(-)
       ---
 (DIR) diff --git 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,
       +                            "<!DOCTYPE html>\n<html>\n\t<head>\n"
       +                            "\t\t<title>%d %s</title>\n\t</head>\n\t<body>\n"
       +                            "\t\t<h1>%d %s</h1>\n\t</body>\n</html>\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,
       -                    "<!DOCTYPE html>\n<html>\n\t<head>\n"
       -                    "\t\t<title>%d %s</title>\n\t</head>\n\t<body>\n"
       -                    "\t\t<h1>%d %s</h1>\n\t</body>\n</html>\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;
       +                }
       +        }
       +}
 (DIR) diff --git 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 */
 (DIR) diff --git 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);
       -
       -                /* 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);
       -                }
       +                http_prepare_error_response(&c.req, &c.res, status);
       +        }
       +
       +        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 */