[master] bdd84ff Make 100-continuation work in H2
Poul-Henning Kamp
phk at FreeBSD.org
Sun Feb 26 23:20:06 CET 2017
commit bdd84ffc5300c25ca8c13b3aefa71e05cad99d26
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Sun Feb 26 22:18:54 2017 +0000
Make 100-continuation work in H2
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index d22dad3..54df7c4 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -62,16 +62,18 @@ CNT_GotReq(struct worker *wrk, struct req *req)
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
+ assert(req->req_body_status != REQ_BODY_INIT);
AN(req->transport->minimal_response);
if (http_GetHdr(req->http, H_Expect, &p)) {
- if (strcasecmp(p, "100-continue")) {
+ if (strcasecmp(p, "100-continue") ||
+ req->http->protover < 11) {
req->doclose = SC_RX_JUNK;
(void)req->transport->minimal_response(req, 417);
wrk->stats->client_req_417++;
return (-1);
}
- if (req->http->protover >= 11 && req->htc->pipeline_b == NULL)
+ if (req->htc->pipeline_b == NULL) // XXX: HTTP1 vs 2 ?
req->want100cont = 1;
http_Unset(req->http, H_Expect);
}
@@ -88,8 +90,6 @@ CNT_GotReq(struct worker *wrk, struct req *req)
return (-1);
}
- assert(req->req_body_status != REQ_BODY_INIT);
-
HTTP_Copy(req->http0, req->http); // For ESI & restart
return (0);
}
diff --git a/bin/varnishd/http2/cache_http2_deliver.c b/bin/varnishd/http2/cache_http2_deliver.c
index dfe2aed..27ce4b3 100644
--- a/bin/varnishd/http2/cache_http2_deliver.c
+++ b/bin/varnishd/http2/cache_http2_deliver.c
@@ -142,7 +142,9 @@ h2_minimal_response(struct req *req, uint16_t status)
/* XXX return code checking once H2_Send returns anything but 0 */
H2_Send(req->wrk, r2, 1,
- H2_FRAME_HEADERS, H2FF_HEADERS_END_HEADERS,
+ H2_FRAME_HEADERS,
+ H2FF_HEADERS_END_HEADERS |
+ (status < 200 ? 0 : H2FF_HEADERS_END_STREAM),
l, buf);
return (0);
}
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 0c5a5e9..c2ab7f1 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -401,7 +401,8 @@ h2_do_req(struct worker *wrk, void *priv)
CAST_OBJ_NOTNULL(req, priv, REQ_MAGIC);
CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
THR_SetRequest(req);
- assert(CNT_Request(wrk, req) != REQ_FSM_DISEMBARK);
+ if (!CNT_GotReq(wrk, req))
+ assert(CNT_Request(wrk, req) != REQ_FSM_DISEMBARK);
THR_SetRequest(NULL);
VSL(SLT_Debug, 0, "H2REQ CNT done");
/* XXX clean up req */
@@ -470,15 +471,12 @@ h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
}
VSLb_ts_req(req, "Req", req->t_req);
http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
+ req->http->protover = 20;
if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
req->req_body_status = REQ_BODY_NONE;
else
req->req_body_status = REQ_BODY_WITHOUT_LEN;
- wrk->stats->client_req++;
- wrk->stats->s_req++;
- req->ws_req = WS_Snapshot(req->ws);
- HTTP_Copy(req->http0, req->http);
req->task.func = h2_do_req;
req->task.priv = req;
diff --git a/bin/varnishtest/tests/t02006.vtc b/bin/varnishtest/tests/t02006.vtc
new file mode 100644
index 0000000..d8354b9
--- /dev/null
+++ b/bin/varnishtest/tests/t02006.vtc
@@ -0,0 +1,27 @@
+varnishtest "H2 POST w/ 100 Continue"
+
+server s1 {
+ rxreq
+ txresp -hdr "Content-Type: text/plain" -body response
+} -start
+
+varnish v1 -vcl+backend {} -cliok "param.set feature +http2" -start
+varnish v1 -cliok "param.set debug +syncvsl"
+
+client c1 {
+ stream 1 {
+ txreq -req POST -hdr expect 100-continue -hdr content-type text/plain -hdr content-length 7 -body request
+
+ rxhdrs
+ expect resp.status == 100
+
+ rxresp
+ expect resp.status == 200
+ expect resp.http.content-Type == "text/plain"
+
+ # Then, payload checks
+ write_body resp.txt
+ shell {grep -q response resp.txt}
+ } -run
+} -run
+
More information about the varnish-commit
mailing list