[master] 4954ed3 Try to push our code into compliance with RFC7230 section 3.3.3

Poul-Henning Kamp phk at FreeBSD.org
Tue Sep 15 15:02:15 CEST 2015


commit 4954ed3b6183bdf712324506fe7bc6074b20c0fe
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 15 13:01:55 2015 +0000

    Try to push our code into compliance with RFC7230 section 3.3.3

diff --git a/bin/varnishd/cache/cache_esi_deliver.c b/bin/varnishd/cache/cache_esi_deliver.c
index c5d3a44..d79cde2 100644
--- a/bin/varnishd/cache/cache_esi_deliver.c
+++ b/bin/varnishd/cache/cache_esi_deliver.c
@@ -238,6 +238,7 @@ VDP_ESI(struct req *req, enum vdp_action act, void **priv,
 		ecx->preq = req;
 		*priv = ecx;
 		RFC2616_Weaken_Etag(req->resp);
+		req->res_mode |= RES_ESI;
 		if (req->resp_len != 0)
 			req->resp_len = -1;
 		return (0);
diff --git a/bin/varnishd/cache/cache_gzip.c b/bin/varnishd/cache/cache_gzip.c
index 7b08f3e..aa516bf 100644
--- a/bin/varnishd/cache/cache_gzip.c
+++ b/bin/varnishd/cache/cache_gzip.c
@@ -299,6 +299,8 @@ VDP_gunzip(struct req *req, enum vdp_action act, void **priv,
 			(void)VGZ_Destroy(&vg);
 			return (-1);
 		}
+
+		req->res_mode |= RES_GUNZIP;
 		VGZ_Obuf(vg, vg->m_buf, vg->m_sz);
 		*priv = vg;
 
diff --git a/bin/varnishd/cache/cache_priv.h b/bin/varnishd/cache/cache_priv.h
index 8fa4a9a..7d69cfa 100644
--- a/bin/varnishd/cache/cache_priv.h
+++ b/bin/varnishd/cache/cache_priv.h
@@ -36,7 +36,7 @@
  * or may not, be talking a "real" HTTP protocol itself.
  */
 
-typedef void vtr_deliver_f (struct req *, struct busyobj *, int wantbody);
+typedef void vtr_deliver_f (struct req *, struct busyobj *, int sendbody);
 
 struct transport {
 	unsigned		magic;
diff --git a/bin/varnishd/cache/cache_range.c b/bin/varnishd/cache/cache_range.c
index 4011e95..6c053fc 100644
--- a/bin/varnishd/cache/cache_range.c
+++ b/bin/varnishd/cache/cache_range.c
@@ -188,7 +188,6 @@ VRG_dorange(struct req *req, const char *r)
 	err = vrg_dorange(req, r);
 	if (err != NULL) {
 		VSLb(req->vsl, SLT_Debug, "RANGE_FAIL %s", err);
-		http_Unset(req->resp, H_Content_Length);
 		if (req->resp_len >= 0)
 			http_PrintfHeader(req->resp,
 			    "Content-Range: bytes */%jd",
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index 92cb781..abd6685 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -52,54 +52,60 @@ cnt_vdp(struct req *req, struct busyobj *bo)
 {
 	const char *r;
 	uint16_t status;
-	int wantbody;
+	int sendbody;
+	intmax_t resp_len;
 
 	CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC);
+
+	resp_len = http_GetContentLength(req->resp);
+	if (bo != NULL)
+		req->resp_len = resp_len;
+	else 
+		req->resp_len = ObjGetLen(req->wrk, req->objcore);
+
 	req->res_mode = 0;
-	wantbody = 1;
+
+	/* RFC 7230, 3.3.3 */
 	status = http_GetStatus(req->resp);
 	if (!strcmp(req->http0->hd[HTTP_HDR_METHOD].b, "HEAD")) {
-		wantbody = 0;
-	} else if (status < 200 || status == 204) {
+		if (req->objcore->flags & OC_F_PASS)
+			sendbody = -1;
+		else
+			sendbody = 0;
+	} else if (status < 200 || status == 204 || status == 304) {
 		req->resp_len = 0;
-		http_Unset(req->resp, H_Content_Length);
-		wantbody = 0;
-	} else if (status == 304) {
-		http_Unset(req->resp, H_Content_Length);
-		wantbody = 0;
-	} else if (bo != NULL)
-		req->resp_len = http_GetContentLength(req->resp);
-	else
-		req->resp_len = ObjGetLen(req->wrk, req->objcore);
+		sendbody = 0;
+	} else
+		sendbody = 1;
 
-	/*
-	 * Determine ESI status first.  Not dependent on wantbody, because
-	 * we want ESI to supress C-L in HEAD too.
-	 */
-	if (!req->disable_esi && req->resp_len != 0 && wantbody &&
-	    ObjGetattr(req->wrk, req->objcore, OA_ESIDATA, NULL) != NULL) {
-		req->res_mode |= RES_ESI;
+	if (!req->disable_esi && req->resp_len != 0 &&
+	    ObjGetattr(req->wrk, req->objcore, OA_ESIDATA, NULL) != NULL)
 		VDP_push(req, VDP_ESI, NULL, 0);
-	}
 
 	if (cache_param->http_gzip_support &&
 	    ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) &&
-	    !RFC2616_Req_Gzip(req->http)) {
-		req->res_mode |= RES_GUNZIP;
+	    !RFC2616_Req_Gzip(req->http))
 		VDP_push(req, VDP_gunzip, NULL, 1);
-	}
 
-	/*
-	 * Range comes after the others and pushes on bottom because
-	 * it can (maybe) generate a correct C-L header.
-	 */
 	if (cache_param->http_range_support && http_IsStatus(req->resp, 200)) {
 		http_SetHeader(req->resp, "Accept-Ranges: bytes");
-		if (wantbody && http_GetHdr(req->http, H_Range, &r))
+		if (sendbody && http_GetHdr(req->http, H_Range, &r))
 			VRG_dorange(req, r);
 	}
 
-	req->transport->deliver(req, bo, wantbody);
+	if (sendbody < 0) {
+		/* Don't touch pass+HEAD C-L */
+		sendbody = 0;
+	} else if (resp_len >= 0 && resp_len == req->resp_len) {
+		/* Reuse C-L header */
+	} else {
+		http_Unset(req->resp, H_Content_Length);
+		if (req->resp_len >= 0 && sendbody)
+			http_PrintfHeader(req->resp,
+			    "Content-Length: %jd", req->resp_len);
+	}
+
+	req->transport->deliver(req, bo, sendbody);
 }
 
 /*--------------------------------------------------------------------
@@ -254,10 +260,12 @@ cnt_synth(struct worker *wrk, struct req *req)
 
 	VCL_synth_method(req->vcl, wrk, req, NULL, synth_body);
 
-	http_Unset(h, H_Content_Length);
-
 	AZ(VSB_finish(synth_body));
 
+	http_Unset(h, H_Content_Length);
+	http_PrintfHeader(req->resp, "Content-Length: %zd",
+	    VSB_len(synth_body));
+
 	/* Discard any lingering request body before delivery */
 	(void)VRB_Ignore(req);
 
diff --git a/bin/varnishd/http1/cache_http1_deliver.c b/bin/varnishd/http1/cache_http1_deliver.c
index fdd176a..997d28b 100644
--- a/bin/varnishd/http1/cache_http1_deliver.c
+++ b/bin/varnishd/http1/cache_http1_deliver.c
@@ -79,7 +79,7 @@ v1d_error(struct req *req, const char *msg)
  */
 
 void __match_proto__(vtr_deliver_f)
-V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
+V1D_Deliver(struct req *req, struct busyobj *bo, int sendbody)
 {
 	enum objiter_status ois;
 
@@ -87,19 +87,10 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
 	CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC);
 	CHECK_OBJ_NOTNULL(req->objcore, OBJCORE_MAGIC);
 
-	if (wantbody) {
-		http_Unset(req->resp, H_Content_Length);
-		if (req->resp_len >= 0)
-			http_PrintfHeader(req->resp,
-			    "Content-Length: %jd", req->resp_len);
-	}
-
-	if (req->resp_len == 0)
-		wantbody = 0;
-	else if (http_GetHdr(req->resp, H_Content_Length, NULL))
-		req->res_mode |= RES_LEN;
-	else if (wantbody) {
-		if (req->http->protover == 11) {
+	if (sendbody) {
+		if (http_GetHdr(req->resp, H_Content_Length, NULL))
+			req->res_mode |= RES_LEN;
+		else if (req->http->protover == 11) {
 			req->res_mode |= RES_CHUNKED;
 			http_SetHeader(req->resp, "Transfer-Encoding: chunked");
 		} else {
@@ -118,7 +109,8 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
 	} else if (!http_GetHdr(req->resp, H_Connection, NULL))
 		http_SetHeader(req->resp, "Connection: keep-alive");
 
-	VDP_push(req, v1d_bytes, NULL, 1);
+	if (sendbody && req->resp_len != 0)
+		VDP_push(req, v1d_bytes, NULL, 1);
 
 	V1L_Reserve(req->wrk, req->ws, &req->sp->fd, req->vsl, req->t_prev);
 
@@ -132,7 +124,7 @@ V1D_Deliver(struct req *req, struct busyobj *bo, int wantbody)
 		(void)V1L_Flush(req->wrk);
 
 	ois = OIS_DONE;
-	if (wantbody) {
+	if (sendbody && req->resp_len != 0) {
 		if (req->res_mode & RES_CHUNKED)
 			V1L_Chunked(req->wrk);
 		ois = VDP_DeliverObj(req);
diff --git a/bin/varnishd/http1/cache_http1_proto.c b/bin/varnishd/http1/cache_http1_proto.c
index 8fa7e9e..8d08278 100644
--- a/bin/varnishd/http1/cache_http1_proto.c
+++ b/bin/varnishd/http1/cache_http1_proto.c
@@ -272,7 +272,7 @@ http1_splitline(struct http *hp, struct http_conn *htc, const int *hf)
 /*--------------------------------------------------------------------*/
 
 static enum body_status
-http1_body_status(struct http *hp, struct http_conn *htc)
+http1_body_status(const struct http *hp, struct http_conn *htc)
 {
 	ssize_t cl;
 	const char *b;



More information about the varnish-commit mailing list