commit c83e450a02fd06d73c5cbc444a1ccd6fc0bf0fa6 from: Omar Polo date: Mon Aug 14 19:52:33 2023 UTC use Transfer-Encoding: chunked only on HTTP/1.1 w3m (HTTP/1.0) doesn't seem to like it. commit - 3b486b32233bf7e55e12e568e2c799990abf9e37 commit + c83e450a02fd06d73c5cbc444a1ccd6fc0bf0fa6 blob - 4122004350c48f4836092646efbd80ac564d455d blob + 62fe18352621f0158077483ff1740b4cf7c4ab32 --- web/http.c +++ web/http.c @@ -112,8 +112,11 @@ http_parse(struct request *req, int fd) if (*t != '\0') *t++ = '\0'; req->path = xstrdup(s); - if (strcmp("HTTP/1.0", t) != 0 && - strcmp("HTTP/1.1", t) != 0) { + if (!strcmp("HTTP/1.0", t)) + req->version = HTTP_1_0; + else if (!strcmp("HTTP/1.1", t)) + req->version = HTTP_1_1; + else { log_warnx("unknown http version: %s", t); return -1; @@ -194,10 +197,11 @@ http_read(struct request *req, int fd) } void -http_response_init(struct reswriter *res, int fd) +http_response_init(struct reswriter *res, struct request *req, int fd) { memset(res, 0, sizeof(*res)); res->fd = fd; + res->chunked = req->version == HTTP_1_1; } int @@ -208,13 +212,12 @@ http_reply(struct reswriter *res, int code, const char int r; res->len = 0; /* discard any leftover from reading */ - res->chunked = ctype != NULL; log_debug("> %d %s", code, reason); if (code >= 300 && code < 400) { location = ctype; - ctype = NULL; + ctype = "text/html;charset=UTF-8"; } r = snprintf(res->buf, sizeof(res->buf), "HTTP/1.1 %d %s\r\n" @@ -231,11 +234,23 @@ http_reply(struct reswriter *res, int code, const char location == NULL ? "" : "Location: ", location == NULL ? "" : location, location == NULL ? "" : "\r\n", - ctype == NULL ? "" : "Transfer-Encoding: chunked\r\n"); + res->chunked ? "Transfer-Encoding: chunked\r\n" : ""); if (r < 0 || (size_t)r >= sizeof(res->buf)) return -1; - return writeall(res, res->buf, r); + if (writeall(res, res->buf, r) == -1) + return -1; + + if (location) { + if (http_writes(res, "") == -1 || + http_htmlescape(res, reason) == -1 || + http_writes(res, "") == -1) + return -1; + } + + return 0; } int @@ -253,6 +268,13 @@ http_flush(struct reswriter *res) if (res->len == 0) return 0; + if (!res->chunked) { + if (writeall(res, res->buf, res->len) == -1) + return -1; + res->len = 0; + return 0; + } + r = snprintf(buf, sizeof(buf), "%zx\r\n", res->len); if (r < 0 || (size_t)r >= sizeof(buf)) { log_warn("snprintf failed"); blob - c457f7765fa8d07caa8b0cb7f255800debb1787f blob + 51cbdb77bac5f32482d1db3184660b2a6e2cac12 --- web/http.h +++ web/http.h @@ -20,12 +20,18 @@ enum http_method { METHOD_POST, }; +enum http_version { + HTTP_1_0, + HTTP_1_1, +}; + struct request { char buf[BUFSIZ]; size_t len; char *path; int method; + int version; char *ctype; size_t clen; }; @@ -40,7 +46,7 @@ struct reswriter { int http_parse(struct request *, int); int http_read(struct request *, int); -void http_response_init(struct reswriter *, int); +void http_response_init(struct reswriter *, struct request *, int); int http_reply(struct reswriter *, int, const char *, const char *); int http_flush(struct reswriter *); int http_write(struct reswriter *, const char *, size_t); blob - 3904a24bfcba03acd812a6e6f3be7564415b3978 blob + 9e64528d62a13660ef647ef40120c6a03dc0efa6 --- web/web.c +++ web/web.c @@ -645,7 +645,7 @@ handle_client(int psock) close(sock); return; } - http_response_init(&res, sock); + http_response_init(&res, &req, sock); route_dispatch(&res, &req); http_flush(&res); http_close(&res);