changeset 19731:e7c075618c6d

lib-http: server: Sometimes a success response was sent before all payload from the client request was read. This can confuse clients, so this is supposed to be prevented.
author Stephan Bosch <stephan@rename-it.nl>
date Mon, 08 Feb 2016 22:53:50 +0100
parents 5a31f0ae5b6f
children 535b6ed4d9ea
files src/lib-http/http-server-connection.c
diffstat 1 files changed, 22 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-http/http-server-connection.c	Mon Feb 08 22:52:38 2016 +0100
+++ b/src/lib-http/http-server-connection.c	Mon Feb 08 22:53:50 2016 +0100
@@ -224,13 +224,30 @@
 		}
 	}
 
-	if (req->state < HTTP_SERVER_REQUEST_STATE_PROCESSING) {
+	/* resource stopped reading payload; update state */
+	switch (req->state) {
+	case HTTP_SERVER_REQUEST_STATE_QUEUED:
+	case HTTP_SERVER_REQUEST_STATE_PAYLOAD_IN:
 		/* finished reading request */
 		req->state = HTTP_SERVER_REQUEST_STATE_PROCESSING;
 		if (req->response != NULL && req->response->submitted)
 			http_server_request_submit_response(req);
-	} else if (req->state == HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE) {
-		http_server_request_ready_to_respond(req);
+		break;
+	case HTTP_SERVER_REQUEST_STATE_PROCESSING:
+		/* no response submitted yet */
+		break;
+	case HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE:
+		/* response submitted, but not all payload is necessarily read */
+		if (http_server_request_is_complete(req))
+			http_server_request_ready_to_respond(req);
+		break;
+	case HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND:
+	case HTTP_SERVER_REQUEST_STATE_FINISHED:
+	case HTTP_SERVER_REQUEST_STATE_ABORTED:
+		/* nothing to do */
+		break;
+	default:
+		i_unreached();
 	}
 
 	/* input stream may have pending input. make sure input handler
@@ -582,7 +599,7 @@
 		}
 
 		if (ret == 0 && pending_request != NULL &&
-			!http_request_parser_pending_payload(conn->http_parser)) {
+			http_server_request_is_complete(pending_request)) {
 			/* previous request is now fully read and ready to respond */
 			http_server_request_ready_to_respond(pending_request);
 		}
@@ -761,7 +778,7 @@
 bool
 http_server_connection_pending_payload(struct http_server_connection *conn)
 {
-	return conn->incoming_payload != NULL;
+	return http_request_parser_pending_payload(conn->http_parser);
 }
 
 static struct connection_settings http_server_connection_set = {