[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