--- /dev/null
+varnishtest "H1 websocket upgrade response received just after a 1xx response"
+
+# When a 1xx interim response and the 101 response of a websocket upgrade are
+# received at once, the websocket key must be searched in the 101 response,
+# not in the interim one which is still present in the buffer.
+
+feature ignore_unknown_macro
+
+server s1 {
+ rxreq
+ expect req.http.upgrade == "websocket"
+ send "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"
+} -start
+
+haproxy h1 -conf {
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ listen li1
+ bind "fd@${li1}"
+ server s1 ${s1_addr}:${s1_port}
+} -start
+
+client c1 -connect ${h1_li1_sock} {
+ txreq -req GET -url /chat \
+ -hdr "Connection: upgrade" \
+ -hdr "Upgrade: websocket" \
+ -hdr "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
+ -hdr "Sec-WebSocket-Version: 13"
+ rxresp
+ expect resp.status == 100
+ rxresp
+ expect resp.status == 101
+ expect resp.http.sec-websocket-accept == "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
+} -run
struct ist n, v;
int ws_key_found = 0;
- blk = htx_get_head_blk(htx); // returns the SL that we skip
- for (blk = htx_get_next_blk(htx, blk); blk; blk = htx_get_next_blk(htx, blk)) {
+ /* Loop backward on the message that was just parsed. because interim
+ * responses (1xx) may still be present before it.
+ */
+ for (blk = htx_get_tail_blk(htx); blk; blk = htx_get_prev_blk(htx, blk)) {
type = htx_get_blk_type(blk);
- if (type != HTX_BLK_HDR)
+ if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL)
break;
+ if (type != HTX_BLK_HDR)
+ continue;
n = htx_get_blk_name(htx, blk);
v = htx_get_blk_value(htx, blk);
/* Websocket key is base64 encoded of 16 bytes */
- if (isteqi(n, ist("sec-websocket-key")) && v.len == 24 &&
- !(h1m->flags & H1_MF_RESP)) {
+ if (!(h1m->flags & H1_MF_RESP) && isteqi(n, ist("sec-websocket-key")) && v.len == 24) {
/* Copy the key on request side
* we might need it if the server is using h2 and does
* not provide the response
ws_key_found = 1;
break;
}
- else if (isteqi(n, ist("sec-websocket-accept")) &&
- h1m->flags & H1_MF_RESP) {
+ else if ((h1m->flags & H1_MF_RESP) && isteqi(n, ist("sec-websocket-accept"))) {
/* Need to verify the response key if the input was
* generated by haproxy
*/