]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: http: Switch the HTTP response in tunnel mode as earlier as possible
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 2 Feb 2018 14:54:15 +0000 (15:54 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 19 Feb 2018 15:47:12 +0000 (16:47 +0100)
When the body length is undefined (no Content-Length or Transfer-Encoding
headers), The reponse remains in ending mode, waiting the request is done. So,
most of time this is not a problem because the resquest is done before the
response. But when a client sends data to a server that replies without waiting
all the data, it is really not desirable to wait the end of the request to
finish the response.

This bug was introduced when the tunneling of the request and the reponse was
refactored, in commit 4be980391 ("MINOR: http: Switch requests/responses in
TUNNEL mode only by checking txn flag").

This patch should be backported in 1.8 and 1.7.

src/proto_http.c

index 5fb510f8dbef07db37b26a30ad5a495557007028..ae582b3deb85433eafee372e5e9beb1541cfdc82 100644 (file)
@@ -4636,16 +4636,8 @@ int http_sync_res_state(struct stream *s)
                         * let's enforce it now that we're not expecting any new
                         * data to come. The caller knows the stream is complete
                         * once both states are CLOSED.
-                        *
-                        * However, there is an exception if the response length
-                        * is undefined. In this case, we switch in TUNNEL mode.
                         */
-                       if (!(txn->rsp.flags & HTTP_MSGF_XFER_LEN)) {
-                               channel_auto_read(chn);
-                               txn->rsp.msg_state = HTTP_MSG_TUNNEL;
-                               chn->flags |= CF_NEVER_WAIT;
-                       }
-                       else if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) {
+                       if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) {
                                channel_shutr_now(chn);
                                channel_shutw_now(chn);
                        }
@@ -6243,6 +6235,8 @@ http_msg_forward_body(struct stream *s, struct http_msg *msg)
                /* The server still sending data that should be filtered */
                if (!(chn->flags & CF_SHUTR) && HAS_DATA_FILTERS(s, chn))
                        goto missing_data_or_waiting;
+               msg->msg_state = HTTP_MSG_TUNNEL;
+               goto ending;
        }
 
        msg->msg_state = HTTP_MSG_ENDING;
@@ -6264,7 +6258,8 @@ http_msg_forward_body(struct stream *s, struct http_msg *msg)
                         /* default_ret */ 1,
                         /* on_error    */ goto error,
                         /* on_wait     */ goto waiting);
-       msg->msg_state = HTTP_MSG_DONE;
+       if (msg->msg_state == HTTP_MSG_ENDING)
+               msg->msg_state = HTTP_MSG_DONE;
        return 1;
 
   missing_data_or_waiting: