]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] http: switch to tunnel mode after status 101 responses
authorWilly Tarreau <w@1wt.eu>
Mon, 1 Feb 2010 14:13:32 +0000 (15:13 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 1 Feb 2010 14:13:32 +0000 (15:13 +0100)
A 101 response is accompanied with an Upgrade header indicating
a new protocol that is spoken on the connection after the exchange
completes. At least we should switch to tunnel mode after such a
response.

doc/configuration.txt
src/proto_http.c

index 4e6f63102aec095126fa0023ad47ee421e57fa49..51e73ee296d1fd374df7d2951a4bd35033cd2d29 100644 (file)
@@ -262,13 +262,17 @@ messages. Let's consider this HTTP response :
 As a special case, HTTP supports so called "Informational responses" as status
 codes 1xx. These messages are special in that they don't convey any part of the
 response, they're just used as sort of a signaling message to ask a client to
-continue to post its request for instance. The requested information will be
-carried by the next non-1xx response message following the informational one.
-This implies that multiple responses may be sent to a single request, and that
-this only works when keep-alive is enabled (1xx messages are HTTP/1.1 only).
-HAProxy handles these messages and is able to correctly forward and skip them,
-and only process the next non-1xx response. As such, these messages are neither
-logged nor transformed, unless explicitly state otherwise.
+continue to post its request for instance. In the case of a status 100 response
+the requested information will be carried by the next non-100 response message
+following the informational one. This implies that multiple responses may be
+sent to a single request, and that this only works when keep-alive is enabled
+(1xx messages are HTTP/1.1 only). HAProxy handles these messages and is able to
+correctly forward and skip them, and only process the next non-100 response. As
+such, these messages are neither logged nor transformed, unless explicitly
+state otherwise. Status 101 messages indicate that the protocol is changing
+over the same connection and that haproxy must switch to tunnel mode, just as
+if a CONNECT had occurred. Then the Upgrade header would contain additional
+information about the type of protocol the connection is switching to.
 
 
 1.3.1. The Response line
index b4ec788150fbd012f45e52ae1939497104c5848a..8a0345a5060377b2ee9c7bd84c8bbad5a0a1fdf6 100644 (file)
@@ -4669,7 +4669,18 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
         * See doc/internals/connection-header.txt for the complete matrix.
         */
 
-       if ((txn->meth != HTTP_METH_CONNECT) &&
+       if (unlikely(txn->status == 101)) {
+               /* this is a "switching protocol" response, we're very unlikely
+                * to understand the next protocols. We have to switch to tunnel
+                * mode, so that we transfer the request and responses then let
+                * this protocol pass unmodified. When we later implement specific
+                * parsers for such protocols, we'll want to check the Upgrade
+                * header which contains information about that protocol (eg: see
+                * RFC2817 about TLS).
+                */
+               txn->flags = (txn->flags & ~TX_CON_WANT_MSK) | TX_CON_WANT_TUN;
+       }
+       else if ((txn->meth != HTTP_METH_CONNECT) &&
            (txn->status >= 200) && !(txn->flags & TX_HDR_CONN_PRS) &&
            ((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN ||
             ((t->fe->options|t->be->options) & PR_O_HTTP_CLOSE))) {
@@ -4778,12 +4789,12 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
                }
 
                /*
-                * We may be facing a 1xx response (100 continue, 101 switching protocols),
-                * in which case this is not the right response, and we're waiting for the
-                * next one. Let's allow this response to go to the client and wait for the
+                * We may be facing a 100-continue response, in which case this
+                * is not the right response, and we're waiting for the next one.
+                * Let's allow this response to go to the client and wait for the
                 * next one.
                 */
-               if (txn->status < 200) {
+               if (unlikely(txn->status == 100)) {
                        hdr_idx_init(&txn->hdr_idx);
                        buffer_forward(rep, rep->lr - msg->sol);
                        msg->msg_state = HTTP_MSG_RPBEFORE;
@@ -4791,6 +4802,8 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
                        rep->analysers |= AN_RES_WAIT_HTTP | an_bit;
                        return 1;
                }
+               else if (unlikely(txn->status < 200))
+                       goto skip_header_mangling;
 
                /* we don't have any 1xx status code now */
 
@@ -4902,6 +4915,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
                                http_change_connection_header(txn, msg, rep, want_flags);
                }
 
+       skip_header_mangling:
                if (txn->flags & TX_RES_XFER_LEN)
                        rep->analysers |= AN_RES_HTTP_XFER_BODY;