changeset 20363:809fe679f218

lib-http: client: Allow retrying requests that failed internally.
author Stephan Bosch <stephan@dovecot.fi>
date Fri, 17 Jun 2016 15:39:36 +0200
parents 7726ef50ccff
children 51790e6d3310
files src/lib-http/http-client-request.c
diffstat 1 files changed, 20 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-client-request.c	Tue Jun 14 22:47:31 2016 +0200
+++ b/src/lib-http/http-client-request.c	Fri Jun 17 15:39:36 2016 +0200
@@ -55,7 +55,7 @@
  * Request
  */
 
-static void
+static bool
 http_client_request_send_error(struct http_client_request *req,
 			       unsigned int status, const char *error);
 
@@ -1071,12 +1071,13 @@
 	return TRUE;
 }
 
-static void
+static bool
 http_client_request_send_error(struct http_client_request *req,
 			       unsigned int status, const char *error)
 {
 	http_client_request_callback_t *callback;
 	bool sending = (req->state == HTTP_REQUEST_STATE_PAYLOAD_OUT);
+	unsigned int orig_attempts = req->attempts;
 
 	req->state = HTTP_REQUEST_STATE_ABORTED;
 
@@ -1088,28 +1089,38 @@
 		http_response_init(&response, status, error);
 		(void)callback(&response, req->context);
 
-		/* release payload early (prevents server/client deadlock in proxy) */
-		if (!sending && req->payload_input != NULL)
-			i_stream_unref(&req->payload_input);
+		if (req->attempts != orig_attempts) {
+			/* retrying */
+			req->callback = callback;
+			http_client_request_resubmit(req);
+			return FALSE;
+		} else {
+			/* release payload early (prevents server/client deadlock in proxy) */
+			if (!sending && req->payload_input != NULL)
+				i_stream_unref(&req->payload_input);
+		}
 	}
 	if (req->payload_wait && req->client->ioloop != NULL)
 		io_loop_stop(req->client->ioloop);
+	return TRUE;
 }
 
 void http_client_request_error_delayed(struct http_client_request **_req)
 {
 	struct http_client_request *req = *_req;
+	bool destroy;
 
 	i_assert(req->state == HTTP_REQUEST_STATE_ABORTED);
 
 	*_req = NULL;
 
 	i_assert(req->delayed_error != NULL && req->delayed_error_status != 0);
-	http_client_request_send_error(req, req->delayed_error_status,
+	destroy = http_client_request_send_error(req, req->delayed_error_status,
 				       req->delayed_error);
 	if (req->queue != NULL)
 		http_client_queue_drop_request(req->queue, req);
-	http_client_request_destroy(&req);
+	if (destroy)
+		http_client_request_destroy(&req);
 }
 
 void http_client_request_error(struct http_client_request **_req,
@@ -1133,8 +1144,8 @@
 		req->delayed_error_status = status;
 		http_client_delay_request_error(req->client, req);
 	} else {
-		http_client_request_send_error(req, status, error);
-		http_client_request_destroy(&req);
+		if (http_client_request_send_error(req, status, error))
+			http_client_request_destroy(&req);
 	}
 	*_req = NULL;
 }