diff options
Diffstat (limited to 'client.c')
-rw-r--r-- | client.c | 24 |
1 files changed, 20 insertions, 4 deletions
@@ -95,7 +95,8 @@ static void client_timeout(struct uloop_timeout *timeout) struct client *cl = container_of(timeout, struct client, timeout); cl->state = CLIENT_STATE_CLOSE; - uh_connection_close(cl); + cl->request.connection_close = true; + uh_request_done(cl); } static void uh_set_client_timeout(struct client *cl, int timeout) @@ -137,6 +138,7 @@ void uh_request_done(struct client *cl) void __printf(4, 5) uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...) { + struct http_request *r = &cl->request; va_list arg; uh_http_header(cl, code, summary); @@ -150,6 +152,17 @@ uh_client_error(struct client *cl, int code, const char *summary, const char *fm va_end(arg); } + /* Close the connection even when keep alive is set, when it + * contains a request body, as it was not read and we are + * currently out of sync. Without handling this the body will be + * interpreted as part of the next request. The alternative + * would be to read and discard the request body here. + */ + if (r->transfer_chunked || r->content_length > 0) { + cl->state = CLIENT_STATE_CLOSE; + cl->request.connection_close = true; + } + uh_request_done(cl); } @@ -194,8 +207,7 @@ static int client_parse_request(struct client *cl, char *data) req->method = h_method; req->version = h_version; - if (req->version < UH_HTTP_VER_1_1 || req->method == UH_HTTP_MSG_POST || - !conf.http_keepalive) + if (req->version < UH_HTTP_VER_1_1 || !conf.http_keepalive) req->connection_close = true; return CLIENT_STATE_HEADER; @@ -396,6 +408,7 @@ void client_poll_post_data(struct client *cl) { struct dispatch *d = &cl->dispatch; struct http_request *r = &cl->request; + enum client_state st; char *buf; int len; @@ -460,10 +473,13 @@ void client_poll_post_data(struct client *cl) buf = ustream_get_read_buf(cl->us, &len); if (!r->content_length && !r->transfer_chunked && cl->state != CLIENT_STATE_DONE) { + st = cl->state; + if (cl->dispatch.data_done) cl->dispatch.data_done(cl); - cl->state = CLIENT_STATE_DONE; + if (cl->state == st) + cl->state = CLIENT_STATE_DONE; } } |