Skip to content

Commit

Permalink
fix chunked transfer encoding in keepalive mode
Browse files Browse the repository at this point in the history
The two commits

  5162e3b
	"allow request handlers to disable chunked reponses"

and

  618493e
	"file: disable chunked encoding for file responses"

broke the chunked transfer encoding handling for proc responses in keep-alive
connections that followed a file response with http status 204 or 304.

The effect of this bug is that cgi responses following a 204 or 304 one where
sent neither in chunked encoding nor with a content-length header, causing
browsers to stall until the keep alive timeout was reached.

Fix the logic flaw by inverting the chunk prevention flag in the client state
and by testing the chunked encoding preconditions every time instead of
once upon client (re-)initialization.

Signed-off-by: Jo-Philipp Wich <[email protected]>
  • Loading branch information
jow- committed Oct 7, 2015
1 parent 1f786a5 commit 7ed2edc
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 10 deletions.
6 changes: 2 additions & 4 deletions client.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void uh_http_header(struct client *cl, int code, const char *summary)

cl->http_code = code;

if (!cl->request.respond_chunked)
if (!uh_use_chunked(cl))
enc = "";

if (r->connection_close)
Expand Down Expand Up @@ -188,8 +188,6 @@ static int client_parse_request(struct client *cl, char *data)
!conf.http_keepalive)
req->connection_close = true;

req->respond_chunked = uh_use_chunked(cl);

return CLIENT_STATE_HEADER;
}

Expand Down Expand Up @@ -261,7 +259,7 @@ static bool tls_redirect_check(struct client *cl)
else if ((ptr = strchr(host, ':')) != NULL)
*ptr = 0;

cl->request.respond_chunked = false;
cl->request.disable_chunked = true;
cl->request.connection_close = true;

uh_http_header(cl, 307, "Temporary Redirect");
Expand Down
2 changes: 1 addition & 1 deletion file.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ static void uh_file_request(struct client *cl, const char *url,
if (fd < 0)
goto error;

req->respond_chunked = false;
req->disable_chunked = true;
cl->dispatch.file.hdr = tb;
uh_file_data(cl, pi, fd);
cl->dispatch.file.hdr = NULL;
Expand Down
2 changes: 1 addition & 1 deletion uhttpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct http_request {
int content_length;
bool expect_cont;
bool connection_close;
bool respond_chunked;
bool disable_chunked;
uint8_t transfer_chunked;
const struct auth_realm *realm;
};
Expand Down
8 changes: 4 additions & 4 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ bool uh_use_chunked(struct client *cl)
if (cl->http_code == 204 || cl->http_code == 304)
return false;

return true;
return !cl->request.disable_chunked;
}

void uh_chunk_write(struct client *cl, const void *data, int len)
{
bool chunked = cl->request.respond_chunked;
bool chunked = uh_use_chunked(cl);

if (cl->state == CLIENT_STATE_CLEANUP)
return;
Expand All @@ -60,7 +60,7 @@ void uh_chunk_vprintf(struct client *cl, const char *format, va_list arg)
return;

uloop_timeout_set(&cl->timeout, conf.network_timeout * 1000);
if (!cl->request.respond_chunked) {
if (!uh_use_chunked(cl)) {
ustream_vprintf(cl->us, format, arg);
return;
}
Expand Down Expand Up @@ -88,7 +88,7 @@ void uh_chunk_printf(struct client *cl, const char *format, ...)

void uh_chunk_eof(struct client *cl)
{
if (!cl->request.respond_chunked)
if (!uh_use_chunked(cl))
return;

if (cl->state == CLIENT_STATE_CLEANUP)
Expand Down

0 comments on commit 7ed2edc

Please sign in to comment.