# HG changeset patch # User Stephan Bosch # Date 1414190323 -10800 # Node ID 4dc3c0cacd2528a05716d96d168d0881db71775d # Parent cffa8349f167964ea116d0128f2cc8b0827d130d lib-http: client: Handle situation in which server sends response before request payload is fully sent. diff -r cffa8349f167 -r 4dc3c0cacd25 src/lib-http/http-client-connection.c --- a/src/lib-http/http-client-connection.c Sat Oct 25 01:38:42 2014 +0300 +++ b/src/lib-http/http-client-connection.c Sat Oct 25 01:38:43 2014 +0300 @@ -632,10 +632,9 @@ return; } - // FIXME: handle somehow if server replies before request->input is at EOF while ((ret=http_response_parse_next (conn->http_parser, payload_type, &response, &error)) > 0) { - bool aborted; + bool aborted, early = FALSE; if (req == NULL) { /* server sent response without any requests in the wait list */ @@ -687,6 +686,16 @@ http_client_connection_debug(conn, "Got unexpected %u response; ignoring", response.status); continue; + } else if (!req->payload_sync && + req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT) { + /* got early response from server while we're still sending request + payload. we cannot recover from this reliably, so we stop sending + payload and close the connection once the response is processed */ + http_client_connection_debug(conn, + "Got early input from server; " + "request payload not completely sent (will close connection)"); + o_stream_unset_flush_callback(conn->conn.output); + conn->output_broken = early = TRUE; } http_client_connection_debug(conn, @@ -710,6 +719,18 @@ if (!aborted) { bool handled = FALSE; + /* response cannot be 2xx if request payload was not completely sent + */ + if (early && response.status / 100 == 2) { + http_client_request_error(req, + HTTP_CLIENT_REQUEST_ERROR_BAD_RESPONSE, + "Server responded with success response " + "before all payload was sent"); + http_client_request_unref(&req); + http_client_connection_close(&conn); + return; + } + /* don't redirect/retry if we're sending data in small blocks via http_client_request_send_payload() and we're not waiting for 100 continue */