From: Willy Tarreau Date: Tue, 28 Sep 2010 12:16:41 +0000 (+0200) Subject: [BUG] stream_sock: try to flush any extra pending request data after a POST X-Git-Tag: v1.5-dev8~459 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58bd8fd46dae559694452a79370d7ebd5c10dce5;p=thirdparty%2Fhaproxy.git [BUG] stream_sock: try to flush any extra pending request data after a POST Some broken browsers still happen to send a CRLF after a POST. Those which send a CRLF in a second packet have it queued into the system's buffers, which causes an RST to be emitted by some systems upon close of the response (eg: Linux). The client may then receive the RST without the last response segments, resulting in a truncated response. This change leaves request polling enabled on a POST so that we can flush any late data from the request buffers. A more complete workaround would consist in reading from the request for a long time, until we get confirmation that the close has been ACKed. This is much more complex and should only be studied for newer versions. (cherry picked from commit 12e316af4f0245fde12dbc224ebe33c8fea806b2) --- diff --git a/src/proto_http.c b/src/proto_http.c index 6875f0aad8..20cd8d1da4 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3834,9 +3834,14 @@ int http_sync_req_state(struct session *s) if (txn->req.msg_state == HTTP_MSG_DONE) { /* No need to read anymore, the request was completely parsed. - * We can shut the read side unless we want to abort_on_close. + * We can shut the read side unless we want to abort_on_close, + * or we have a POST request. The issue with POST requests is + * that some browsers still send a CRLF after the request, and + * this CRLF must be read so that it does not remain in the kernel + * buffers, otherwise a close could cause an RST on some systems + * (eg: Linux). */ - if (buf->cons->state == SI_ST_EST || !(s->be->options & PR_O_ABRT_CLOSE)) + if (!(s->be->options & PR_O_ABRT_CLOSE) && txn->meth != HTTP_METH_POST) buffer_dont_read(buf); if (txn->rsp.msg_state == HTTP_MSG_ERROR) @@ -4272,6 +4277,14 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit) buffer_auto_read(req); buffer_auto_close(req); } + else if (s->txn.meth == HTTP_METH_POST) { + /* POST requests may require to read extra CRLF + * sent by broken browsers and which could cause + * an RST to be sent upon close on some systems + * (eg: Linux). + */ + buffer_auto_read(req); + } return 0; }