BUG/MINOR: http: don't abort client connection on premature responses

When a server responds prematurely to a POST request, haproxy used to
cause the transfer to be aborted before the end. This is problematic
because this causes the client to receive a TCP reset when it tries to
push more data, generally preventing it from receiving the response
which contain the reason for the premature reponse (eg: "entity too
large" or an authentication request).

From now on we take care of allowing the upload traffic to flow to the
server even when the response has been received, since the server is
supposed to drain it. That way the client receives the server response.

This bug has been present since 1.4 and the fix should probably be
backported there.
diff --git a/src/proto_http.c b/src/proto_http.c
index 6ec1d64..5354284 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3751,7 +3751,8 @@
 	/* if the server closes the connection, we want to immediately react
 	 * and close the socket to save packets and syscalls.
 	 */
-	req->cons->flags |= SI_FL_NOHALF;
+	if (!(req->analysers & AN_REQ_HTTP_XFER_BODY))
+		req->cons->flags |= SI_FL_NOHALF;
 
 	s->logs.tv_request = now;
 	/* OK let's go on with the BODY now */
@@ -4182,6 +4183,11 @@
 		if (!(s->be->options & PR_O_ABRT_CLOSE) && txn->meth != HTTP_METH_POST)
 			channel_dont_read(chn);
 
+		/* if the server closes the connection, we want to immediately react
+		 * and close the socket to save packets and syscalls.
+		 */
+		chn->cons->flags |= SI_FL_NOHALF;
+
 		if (txn->rsp.msg_state == HTTP_MSG_ERROR)
 			goto wait_other_side;
 
@@ -4453,10 +4459,10 @@
 		channel_auto_close(s->rep);
 		channel_auto_read(s->rep);
 	}
-	else if (txn->rsp.msg_state == HTTP_MSG_CLOSED ||
+	else if ((txn->req.msg_state >= HTTP_MSG_DONE &&
+		  (txn->rsp.msg_state == HTTP_MSG_CLOSED || (s->rep->flags & CF_SHUTW))) ||
 		 txn->rsp.msg_state == HTTP_MSG_ERROR ||
-		 txn->req.msg_state == HTTP_MSG_ERROR ||
-		 (s->rep->flags & CF_SHUTW)) {
+		 txn->req.msg_state == HTTP_MSG_ERROR) {
 		s->rep->analysers = 0;
 		channel_auto_close(s->rep);
 		channel_auto_read(s->rep);