]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: Don't try to automatically retry requests whose payload was already lost.
authorTimo Sirainen <tss@iki.fi>
Sun, 8 Dec 2013 21:41:33 +0000 (23:41 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 8 Dec 2013 21:41:33 +0000 (23:41 +0200)
Patch by Stephan Bosch.

src/lib-http/http-client-connection.c
src/lib-http/http-client-request.c

index dd708f58e15611cb37d28c567aacc5f25942ee6c..bd0044ddb031d7b989ee5174584c21f5443f7945 100644 (file)
@@ -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) {
index aedc6fbec2716a3a91e736ebff092e7bb339fd3d..a17e59d32f65cc2d5a29ebd3f020f22612d9c2f4 100644 (file)
@@ -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 */