dovecot-2.2: http: Preparse Retry-After header if response statu...

dovecot at dovecot.org dovecot at dovecot.org
Fri Nov 22 22:13:13 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/c215131c2c18
changeset: 17004:c215131c2c18
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Fri Nov 22 22:08:44 2013 +0200
description:
http: Preparse Retry-After header if response status is 503 or 3xx.

diffstat:

 src/lib-http/http-response-parser.c |  53 +++++++++++++++++++++++++++++++++++++
 src/lib-http/http-response.h        |   2 +-
 2 files changed, 54 insertions(+), 1 deletions(-)

diffs (100 lines):

diff -r 6b48a5675512 -r c215131c2c18 src/lib-http/http-response-parser.c
--- a/src/lib-http/http-response-parser.c	Fri Nov 22 22:08:20 2013 +0200
+++ b/src/lib-http/http-response-parser.c	Fri Nov 22 22:08:44 2013 +0200
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "istream.h"
 #include "http-parser.h"
+#include "http-date.h"
 #include "http-message-parser.h"
 #include "http-response-parser.h"
 
@@ -232,10 +233,41 @@
 	return 0;
 }
 
+static int
+http_response_parse_retry_after(const char *hdrval, time_t resp_time,
+	time_t *retry_after_r)
+{
+	time_t delta;
+
+	/* http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-23
+	     Section 7.1.3:
+
+	   The value of this field can be either an HTTP-date or an integer
+	   number of seconds (in decimal) after the time of the response.
+	   Time spans are non-negative decimal integers, representing time in
+	   seconds.
+
+     Retry-After = HTTP-date / delta-seconds
+     delta-seconds  = 1*DIGIT
+	 */
+	if (str_to_time(hdrval, &delta) >= 0) {
+		if (resp_time == (time_t)-1) {
+			return -1;
+		}
+		*retry_after_r = resp_time + delta;
+		return 0;
+	}
+
+	return (http_date_parse
+		((unsigned char *)hdrval, strlen(hdrval), retry_after_r) ? 0 : -1);
+}
+
 int http_response_parse_next(struct http_response_parser *parser,
 			     enum http_response_payload_type payload_type,
 			     struct http_response *response, const char **error_r)
 {
+	const char *hdrval;
+	time_t retry_after = (time_t)-1;
 	int ret;
 
 	/* make sure we finished streaming payload from previous response
@@ -300,6 +332,26 @@
 		}
 	}
 
+	/* http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-23
+	     Section 7.1.3:
+	
+	   Servers send the "Retry-After" header field to indicate how long the
+	   user agent ought to wait before making a follow-up request.  When
+	   sent with a 503 (Service Unavailable) response, Retry-After indicates
+	   how long the service is expected to be unavailable to the client.
+	   When sent with any 3xx (Redirection) response, Retry-After indicates
+	   the minimum time that the user agent is asked to wait before issuing
+	   the redirected request.
+	 */
+	if (parser->response_status == 503 || (parser->response_status / 100) == 3) {		
+		hdrval = http_header_field_get(parser->parser.msg.header, "Retry-After");
+		if (hdrval != NULL) {
+			(void)http_response_parse_retry_after
+				(hdrval, parser->parser.msg.date, &retry_after);
+			/* broken Retry-After header is ignored */
+		}
+	}
+
 	parser->state = HTTP_RESPONSE_PARSE_STATE_INIT;
 
 	memset(response, 0, sizeof(*response));
@@ -309,6 +361,7 @@
 	response->version_minor = parser->parser.msg.version_minor;
 	response->location = parser->parser.msg.location;
 	response->date = parser->parser.msg.date;
+	response->retry_after = retry_after;
 	response->payload = parser->parser.payload;
 	response->header = parser->parser.msg.header;
 	response->headers = *http_header_get_fields(response->header); /* FIXME: remove in v2.3 */
diff -r 6b48a5675512 -r c215131c2c18 src/lib-http/http-response.h
--- a/src/lib-http/http-response.h	Fri Nov 22 22:08:20 2013 +0200
+++ b/src/lib-http/http-response.h	Fri Nov 22 22:08:44 2013 +0200
@@ -22,7 +22,7 @@
 	const char *reason;
 	const char *location;
 
-	time_t date;
+	time_t date, retry_after;
 	const struct http_header *header;
 	struct istream *payload;
 


More information about the dovecot-cvs mailing list