mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-28 14:21:00 +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
|
||||
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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user