]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[BUG] stream_sock: try to flush any extra pending request data after a POST
authorWilly Tarreau <w@1wt.eu>
Tue, 28 Sep 2010 12:16:41 +0000 (14:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 30 Oct 2010 17:04:30 +0000 (19:04 +0200)
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)

src/proto_http.c

index 6875f0aad8858d96da6ea909f3ab538971315d1b..20cd8d1da441206c49a9fe33a5c0d8e4eea869fd 100644 (file)
@@ -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;
                }