[master] 5a0817d Move minimal reponses to the transport level and use them for H1 100/400/417

Nils Goroll nils.goroll at uplex.de
Thu Feb 23 17:46:05 CET 2017


commit 5a0817d1446c64467745e50fb9d9ab0e791e9bec
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Thu Feb 23 17:44:26 2017 +0100

    Move minimal reponses to the transport level and use them for H1 100/400/417
    
    Also log such resposenses

diff --git a/bin/varnishd/cache/cache_transport.h b/bin/varnishd/cache/cache_transport.h
index 2633cfe..447c427 100644
--- a/bin/varnishd/cache/cache_transport.h
+++ b/bin/varnishd/cache/cache_transport.h
@@ -42,6 +42,7 @@ typedef void vtr_sess_panic_f (struct vsb *, const struct sess *);
 typedef void vtr_req_panic_f (struct vsb *, const struct req *);
 typedef void vtr_req_fail_f (struct req *, enum sess_close);
 typedef void vtr_reembark_f (struct worker *, struct req *);
+typedef int vtr_minimal_response_f (struct req *, uint16_t status);
 
 struct transport {
 	unsigned			magic;
@@ -60,6 +61,7 @@ struct transport {
 	vtr_sess_panic_f		*sess_panic;
 	vtr_req_panic_f			*req_panic;
 	vtr_reembark_f			*reembark;
+	vtr_minimal_response_f		*minimal_response;
 
 	VTAILQ_ENTRY(transport)		list;
 };
diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c
index 06eb34b..1dfe146 100644
--- a/bin/varnishd/http1/cache_http1_fsm.c
+++ b/bin/varnishd/http1/cache_http1_fsm.c
@@ -202,6 +202,41 @@ http1_reembark(struct worker *wrk, struct req *req)
 	usleep(10000);
 }
 
+static int __match_proto__(vtr_minimal_response_f)
+http1_minimal_response(struct req *req, uint16_t status)
+{
+	size_t wl, l, spc = 80;
+	char buf[spc];
+	const char *reason;
+
+	assert(status >= 100);
+	assert(status < 1000);
+
+	reason = http_Status2Reason(status, NULL);
+
+	l = snprintf(buf, spc,
+	    "HTTP/1.1 %03d %s\r\n\r\n", status, reason);
+	assert (l < spc);
+
+	VSLb(req->vsl, SLT_RespProtocol, "HTTP/1.1");
+	VSLb(req->vsl, SLT_RespStatus, "%03d", status);
+	VSLb(req->vsl, SLT_RespReason, "%s", reason);
+
+	if (status >= 400)
+		req->err_code = status;
+	wl = write(req->sp->fd, buf, l);
+
+	if (wl > 0)
+		req->acct.resp_hdrbytes += wl;
+	if (wl != l) {
+		VTCP_Assert(1);
+		if (! req->doclose)
+			req->doclose = SC_REM_CLOSE;
+		return (-1);
+	}
+	return (0);
+}
+
 struct transport HTTP1_transport = {
 	.name =			"HTTP/1",
 	.magic =		TRANSPORT_MAGIC,
@@ -213,19 +248,25 @@ struct transport HTTP1_transport = {
 	.sess_panic =		http1_sess_panic,
 	.req_panic =		http1_req_panic,
 	.reembark =		http1_reembark,
+	.minimal_response =	http1_minimal_response,
 };
 
 /*----------------------------------------------------------------------
  */
 
+static inline void
+http1_abort(struct req *req, unsigned status)
+{
+	AN(req->doclose);
+	assert(status >= 400);
+	(void) http1_minimal_response(req, status);
+	return;
+}
+
 static int
 http1_dissect(struct worker *wrk, struct req *req)
 {
-	const char *r_100 = "HTTP/1.1 100 Continue\r\n\r\n";
-	const char *r_400 = "HTTP/1.1 400 Bad Request\r\n\r\n";
-	const char *r_417 = "HTTP/1.1 417 Expectation Failed\r\n\r\n";
 	const char *p;
-	ssize_t r;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
@@ -256,10 +297,8 @@ http1_dissect(struct worker *wrk, struct req *req)
 		    (int)(req->htc->rxbuf_e - req->htc->rxbuf_b),
 		    req->htc->rxbuf_b);
 		wrk->stats->client_req_400++;
-		r = write(req->sp->fd, r_400, strlen(r_400));
-		if (r > 0)
-			req->acct.resp_hdrbytes += r;
 		req->doclose = SC_RX_JUNK;
+		http1_abort(req, 400);
 		return (-1);
 	}
 
@@ -284,21 +323,14 @@ http1_dissect(struct worker *wrk, struct req *req)
 
 	if (http_GetHdr(req->http, H_Expect, &p)) {
 		if (strcasecmp(p, "100-continue")) {
-			wrk->stats->client_req_417++;
-			req->err_code = 417;
-			r = write(req->sp->fd, r_417, strlen(r_417));
-			if (r > 0)
-				req->acct.resp_hdrbytes += r;
 			req->doclose = SC_RX_JUNK;
+			http1_abort(req, 417);
+			wrk->stats->client_req_417++;
 			return (-1);
 		}
-		r = write(req->sp->fd, r_100, strlen(r_100));
-		if (r > 0)
-			req->acct.resp_hdrbytes += r;
-		if (r != strlen(r_100)) {
-			req->doclose = SC_REM_CLOSE;
+		http1_simple_response(req, R_100);
+		if (req->doclose)
 			return (-1);
-		}
 		http_Unset(req->http, H_Expect);
 	}
 
@@ -310,9 +342,7 @@ http1_dissect(struct worker *wrk, struct req *req)
 
 	req->doclose = http_DoConnection(req->http);
 	if (req->doclose == SC_RX_BAD) {
-		r = write(req->sp->fd, r_400, strlen(r_400));
-		if (r > 0)
-			req->acct.resp_hdrbytes += r;
+		http1_abort(req, 400);
 		return (-1);
 	}
 
diff --git a/bin/varnishd/http2/cache_http2.h b/bin/varnishd/http2/cache_http2.h
index bf9604c..a9a44ef 100644
--- a/bin/varnishd/http2/cache_http2.h
+++ b/bin/varnishd/http2/cache_http2.h
@@ -125,6 +125,7 @@ vtr_sess_panic_f h2_sess_panic;
 /* http2/cache_http2_deliver.c */
 #ifdef TRANSPORT_MAGIC
 vtr_deliver_f h2_deliver;
+vtr_minimal_response_f h2_minimal_response;
 #endif /* TRANSPORT_MAGIC */
 
 /* http2/cache_http2_hpack.c */
diff --git a/bin/varnishd/http2/cache_http2_deliver.c b/bin/varnishd/http2/cache_http2_deliver.c
index f21631c..a589428 100644
--- a/bin/varnishd/http2/cache_http2_deliver.c
+++ b/bin/varnishd/http2/cache_http2_deliver.c
@@ -92,6 +92,61 @@ h2_bytes(struct req *req, enum vdp_action act, void **priv,
 	return (0);
 }
 
+static inline size_t
+h2_status(uint8_t *p, uint16_t status) {
+	size_t l = 1;
+
+	switch (status) {
+	case 200: *p = 0x80 |  8; break;
+	case 204: *p = 0x80 |  9; break;
+	case 206: *p = 0x80 | 10; break;
+	case 304: *p = 0x80 | 11; break;
+	case 400: *p = 0x80 | 12; break;
+	case 404: *p = 0x80 | 13; break;
+	case 500: *p = 0x80 | 14; break;
+	default:
+		*p++ = 0x18;
+		*p++ = 0x03;
+		l = 2;
+
+		l += snprintf((char*)p, 4, "%03d", status);
+		assert(l == 5);
+		break;
+	}
+
+	return (l);
+}
+
+int __match_proto__(vtr_minimal_response_f)
+h2_minimal_response(struct req *req, uint16_t status)
+{
+	struct h2_req *r2;
+	const size_t spc = 6;
+	size_t l;
+	uint8_t buf[spc];
+
+	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
+
+	assert(status >= 100);
+	assert(status < 1000);
+
+	l = h2_status(buf, status);
+	assert(l < spc);
+
+	VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
+	VSLb(req->vsl, SLT_RespStatus, "%03d", status);
+	VSLb(req->vsl, SLT_RespReason, "%s", http_Status2Reason(status, NULL));
+
+	if (status >= 400)
+		req->err_code = status;
+
+	H2_Send(req->wrk, r2, 1,
+	    H2_FRAME_HEADERS, H2FF_HEADERS_END_HEADERS,
+	    l, buf);
+	return (0);
+}
+
 void __match_proto__(vtr_deliver_f)
 h2_deliver(struct req *req, struct boc *boc, int sendbody)
 {
@@ -118,22 +173,7 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
 	(void)WS_Reserve(req->ws, 0);
 	p = (void*)req->ws->f;
 
-	switch (req->resp->status) {
-	case 200: *p++ = 0x80 |  8; break;
-	case 204: *p++ = 0x80 |  9; break;
-	case 206: *p++ = 0x80 | 10; break;
-	case 304: *p++ = 0x80 | 11; break;
-	case 400: *p++ = 0x80 | 12; break;
-	case 404: *p++ = 0x80 | 13; break;
-	case 500: *p++ = 0x80 | 14; break;
-	default:
-		*p++ = 0x18;
-		*p++ = 0x03;
-
-		assert(snprintf((char*)p, 4, "%03d", req->resp->status) == 3);
-		p += 3;
-		break;
-	}
+	p += h2_status(p, req->resp->status);
 
 	hp = req->resp;
 	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 00fda7c..26a0347 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -831,4 +831,5 @@ struct transport H2_transport = {
 	.new_session =		h2_new_session,
 	.sess_panic =		h2_sess_panic,
 	.deliver =		h2_deliver,
+	.minimal_response =	h2_minimal_response,
 };
diff --git a/include/tbl/http_response.h b/include/tbl/http_response.h
index eaa74c4..0e21d00 100644
--- a/include/tbl/http_response.h
+++ b/include/tbl/http_response.h
@@ -30,6 +30,7 @@
 
 /*lint -save -e525 -e539 */
 
+HTTP_RESP(100, "Continue")
 HTTP_RESP(101, "Switching Protocols")
 HTTP_RESP(200, "OK")
 HTTP_RESP(201, "Created")



More information about the varnish-commit mailing list