diff --git a/doc/configuration.txt b/doc/configuration.txt index 4e6f63102..51e73ee29 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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 diff --git a/src/proto_http.c b/src/proto_http.c index b4ec78815..8a0345a50 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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;