From: Timo Sirainen Date: Sun, 8 Dec 2013 21:41:33 +0000 (+0200) Subject: lib-http: Don't try to automatically retry requests whose payload was already lost. X-Git-Tag: 2.2.10~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=35df1d3e03ffb05ee21077018f5154a4b1e47e37;p=thirdparty%2Fdovecot%2Fcore.git lib-http: Don't try to automatically retry requests whose payload was already lost. Patch by Stephan Bosch. --- diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c index dd708f58e1..bd0044ddb0 100644 --- a/src/lib-http/http-client-connection.c +++ b/src/lib-http/http-client-connection.c @@ -596,31 +596,37 @@ static void http_client_connection_input(struct connection *_conn) if (!aborted) { bool handled = FALSE; - /* failed Expect: */ - if (response.status == 417 && req->payload_sync) { - /* drop Expect: continue */ - req->payload_sync = FALSE; - conn->output_locked = FALSE; - conn->peer->no_payload_sync = TRUE; - if (http_client_request_try_retry(req)) - handled = TRUE; - /* redirection */ - } else if (!req->client->set.no_auto_redirect && - response.status / 100 == 3 && response.status != 304 && - response.location != NULL) { - /* redirect (possibly after delay) */ - if (http_client_request_delay_from_response(req, &response) >= 0) { - http_client_request_redirect - (req, response.status, response.location); - handled = TRUE; + /* 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 */ + if (!req->payload_wait || + (req->payload_sync && !conn->payload_continue)) { + /* failed Expect: */ + if (response.status == 417 && req->payload_sync) { + /* drop Expect: continue */ + req->payload_sync = FALSE; + conn->output_locked = FALSE; + conn->peer->no_payload_sync = TRUE; + if (http_client_request_try_retry(req)) + handled = TRUE; + /* redirection */ + } else if (!req->client->set.no_auto_redirect && + response.status / 100 == 3 && response.status != 304 && + response.location != NULL) { + /* redirect (possibly after delay) */ + if (http_client_request_delay_from_response(req, &response) >= 0) { + http_client_request_redirect + (req, response.status, response.location); + handled = TRUE; + } + /* service unavailable */ + } else if (response.status == 503) { + /* automatically retry after delay if indicated */ + if ( response.retry_after != (time_t)-1 && + http_client_request_delay_from_response(req, &response) > 0 && + http_client_request_try_retry(req)) + handled = TRUE; } - /* service unavailable */ - } else if (response.status == 503) { - /* automatically retry after delay if indicated */ - if ( response.retry_after != (time_t)-1 && - http_client_request_delay_from_response(req, &response) > 0 && - http_client_request_try_retry(req)) - handled = TRUE; } if (!handled) { diff --git a/src/lib-http/http-client-request.c b/src/lib-http/http-client-request.c index aedc6fbec2..a17e59d32f 100644 --- a/src/lib-http/http-client-request.c +++ b/src/lib-http/http-client-request.c @@ -622,21 +622,23 @@ static int http_client_request_send_real(struct http_client_request *req, if (!req->have_hdr_expect && req->payload_sync) { str_append(rtext, "Expect: 100-continue\r\n"); } - if (req->payload_chunked) { - // FIXME: can't do this for a HTTP/1.0 server - if (!req->have_hdr_body_spec) - str_append(rtext, "Transfer-Encoding: chunked\r\n"); - req->payload_output = - http_transfer_chunked_ostream_create(output); - } else if (req->payload_input != NULL) { - /* send Content-Length if we have specified a payload, - even if it's 0 bytes. */ - if (!req->have_hdr_body_spec) { - str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n", - req->payload_size); + if (req->payload_input != NULL) { + if (req->payload_chunked) { + // FIXME: can't do this for a HTTP/1.0 server + if (!req->have_hdr_body_spec) + str_append(rtext, "Transfer-Encoding: chunked\r\n"); + req->payload_output = + http_transfer_chunked_ostream_create(output); + } else { + /* send Content-Length if we have specified a payload, + even if it's 0 bytes. */ + if (!req->have_hdr_body_spec) { + str_printfa(rtext, "Content-Length: %"PRIuUOFF_T"\r\n", + req->payload_size); + } + req->payload_output = output; + o_stream_ref(output); } - req->payload_output = output; - o_stream_ref(output); } if (!req->have_hdr_connection && req->host_url == &req->origin_url) { /* https://tools.ietf.org/html/rfc2068 @@ -814,6 +816,8 @@ void http_client_request_redirect(struct http_client_request *req, struct http_url *url; const char *error, *target, *origin_url; + i_assert(!req->payload_wait); + /* parse URL */ if (http_url_parse(location, NULL, 0, pool_datastack_create(), &url, &error) < 0) { @@ -901,6 +905,8 @@ void http_client_request_redirect(struct http_client_request *req, void http_client_request_resubmit(struct http_client_request *req) { + i_assert(!req->payload_wait); + http_client_request_debug(req, "Resubmitting request"); /* rewind payload stream */