mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-12-01 15:51:01 +01:00
[MEDIUM] http: switch to tunnel mode after status 101 responses
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.
This commit is contained in:
parent
95fa4698f1
commit
5843d1a894
@ -262,13 +262,17 @@ messages. Let's consider this HTTP response :
|
|||||||
As a special case, HTTP supports so called "Informational responses" as status
|
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
|
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
|
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
|
continue to post its request for instance. In the case of a status 100 response
|
||||||
carried by the next non-1xx response message following the informational one.
|
the requested information will be carried by the next non-100 response message
|
||||||
This implies that multiple responses may be sent to a single request, and that
|
following the informational one. This implies that multiple responses may be
|
||||||
this only works when keep-alive is enabled (1xx messages are HTTP/1.1 only).
|
sent to a single request, and that this only works when keep-alive is enabled
|
||||||
HAProxy handles these messages and is able to correctly forward and skip them,
|
(1xx messages are HTTP/1.1 only). HAProxy handles these messages and is able to
|
||||||
and only process the next non-1xx response. As such, these messages are neither
|
correctly forward and skip them, and only process the next non-100 response. As
|
||||||
logged nor transformed, unless explicitly state otherwise.
|
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
|
1.3.1. The Response line
|
||||||
|
|||||||
@ -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.
|
* 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->status >= 200) && !(txn->flags & TX_HDR_CONN_PRS) &&
|
||||||
((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN ||
|
((txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_TUN ||
|
||||||
((t->fe->options|t->be->options) & PR_O_HTTP_CLOSE))) {
|
((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),
|
* We may be facing a 100-continue response, in which case this
|
||||||
* in which case this is not the right response, and we're waiting for the
|
* is not the right response, and we're waiting for the next one.
|
||||||
* next one. Let's allow this response to go to the client and wait for the
|
* Let's allow this response to go to the client and wait for the
|
||||||
* next one.
|
* next one.
|
||||||
*/
|
*/
|
||||||
if (txn->status < 200) {
|
if (unlikely(txn->status == 100)) {
|
||||||
hdr_idx_init(&txn->hdr_idx);
|
hdr_idx_init(&txn->hdr_idx);
|
||||||
buffer_forward(rep, rep->lr - msg->sol);
|
buffer_forward(rep, rep->lr - msg->sol);
|
||||||
msg->msg_state = HTTP_MSG_RPBEFORE;
|
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;
|
rep->analysers |= AN_RES_WAIT_HTTP | an_bit;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (unlikely(txn->status < 200))
|
||||||
|
goto skip_header_mangling;
|
||||||
|
|
||||||
/* we don't have any 1xx status code now */
|
/* 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);
|
http_change_connection_header(txn, msg, rep, want_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_header_mangling:
|
||||||
if (txn->flags & TX_RES_XFER_LEN)
|
if (txn->flags & TX_RES_XFER_LEN)
|
||||||
rep->analysers |= AN_RES_HTTP_XFER_BODY;
|
rep->analysers |= AN_RES_HTTP_XFER_BODY;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user