@@ -42,6 +42,21 @@ const char * const http_methods[] = {
[UH_HTTP_MSG_OPTIONS] = "OPTIONS",
};
+static int chunked_write_cb(struct ustream *s, const char *buf, int len, bool more)
+{
+ struct client *cl = container_of(s, struct client, chunked);
+ ustream_printf(cl->us, "%X\r\n", len);
+ ustream_write(cl->us, buf, len, more);
+ ustream_printf(cl->us, "\r\n");
+ return len;
+}
+
+static void chunked_init(struct client *cl)
+{
+ ustream_init_defaults(&cl->chunked);
+ cl->chunked.write = &chunked_write_cb;
+}
+
void uh_http_header(struct client *cl, int code, const char *summary)
{
struct http_request *r = &cl->request;
@@ -52,6 +67,8 @@ void uh_http_header(struct client *cl, int code, const char *summary)
if (!cl->request.respond_chunked)
enc = "";
+ else
+ chunked_init(cl);
if (r->connection_close)
conn = "Connection: close";
@@ -579,8 +579,10 @@ static void uh_file_data(struct client *cl, struct path_info *pi, int fd)
ustream_printf(cl->us, "Content-Type: %s\r\n",
uh_file_mime_lookup(pi->name));
- ustream_printf(cl->us, "Content-Length: %" PRIu64 "\r\n\r\n",
- pi->stat.st_size);
+ if (!cl->request.respond_chunked)
+ ustream_printf(cl->us, "Content-Length: %" PRIu64 "\r\n",
+ pi->stat.st_size);
+ ustream_printf(cl->us, "\r\n");
/* send body */
@@ -236,6 +236,7 @@ struct client {
struct ustream *us;
struct ustream_fd sfd;
+ struct ustream chunked;
#ifdef HAVE_TLS
struct ustream_ssl ssl;
#endif
@@ -37,44 +37,27 @@ bool uh_use_chunked(struct client *cl)
void uh_chunk_write(struct client *cl, const void *data, int len)
{
- bool chunked = cl->request.respond_chunked;
-
if (cl->state == CLIENT_STATE_CLEANUP)
return;
uloop_timeout_set(&cl->timeout, conf.network_timeout * 1000);
- if (chunked)
- ustream_printf(cl->us, "%X\r\n", len);
- ustream_write(cl->us, data, len, true);
- if (chunked)
- ustream_printf(cl->us, "\r\n", len);
+
+ if (!cl->request.respond_chunked)
+ ustream_write(cl->us, data, len, true);
+ else
+ ustream_write(&cl->chunked, data, len, true);
}
void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg)
{
- char buf[256];
- va_list arg2;
- int len;
-
if (cl->state == CLIENT_STATE_CLEANUP)
return;
uloop_timeout_set(&cl->timeout, conf.network_timeout * 1000);
- if (!cl->request.respond_chunked) {
+ if (!cl->request.respond_chunked)
ustream_vprintf(cl->us, format, arg);
- return;
- }
-
- va_copy(arg2, arg);
- len = vsnprintf(buf, sizeof(buf), format, arg2);
- va_end(arg2);
-
- ustream_printf(cl->us, "%X\r\n", len);
- if (len < sizeof(buf))
- ustream_write(cl->us, buf, len, true);
else
- ustream_vprintf(cl->us, format, arg);
- ustream_printf(cl->us, "\r\n", len);
+ ustream_vprintf(&cl->chunked, format, arg);
}
void uh_chunk_printf(struct client *cl, const char *format, ...)
Hi, this patch simplifies chunk printing when chunked transfer encoding is used in a response... And it comes handy when gzip content encoding will be used. Signed-off-by: Andrej Krpic <ak77@tnode.com> --- client.c | 17 +++++++++++++++++ file.c | 6 ++++-- uhttpd.h | 1 + utils.c | 31 +++++++------------------------ 4 files changed, 29 insertions(+), 26 deletions(-)