[4.0] 419a08f Fix a cornercase related to empty pass objects.

Martin Blix Grydeland martin at varnish-software.com
Fri Nov 7 14:17:23 CET 2014


commit 419a08f5362a0b9885ecae5cc443fb82e2c3c002
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Oct 21 09:00:52 2014 +0000

    Fix a cornercase related to empty pass objects.
    
    Fixes #1612
    Testcase by: 	daghf
    
    Conflicts:
    	bin/varnishd/cache/cache_http1_deliver.c

diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index 73aea69..9b0d51b 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -240,29 +240,36 @@ V1D_Deliver(struct req *req, struct busyobj *bo)
 
 	req->res_mode = 0;
 
+	if (req->esi_level > 0)
+		req->res_mode |= RES_ESI_CHILD;
+
 	if (!req->disable_esi && req->obj->esidata != NULL) {
 		/* In ESI mode, we can't know the aggregate length */
-		req->res_mode &= ~RES_LEN;
 		req->res_mode |= RES_ESI;
+		RFC2616_Weaken_Etag(req->resp);
+	}
+
+	if (req->res_mode & (RES_ESI_CHILD|RES_ESI)) {
+		/* nothing */
 	} else if (req->resp->status == 304) {
 		req->res_mode &= ~RES_LEN;
 		http_Unset(req->resp, H_Content_Length);
 		req->wantbody = 0;
-	} else if (bo == NULL) {
-		/* XXX: Not happy with this convoluted test */
+	} else if (bo != NULL) {
+		/* Streaming, decide CHUNKED/EOF later */
+	} else if ((req->obj->objcore->flags & OC_F_PASS) && !req->wantbody) {
+		/*
+		 * if we pass a HEAD the C-L header may already be in the
+		 * object and it will not match the actual storage length
+		 * which is zero.
+		 * Hand that C-L header back to client.
+		 */
 		req->res_mode |= RES_LEN;
-		if (!(req->obj->objcore->flags & OC_F_PASS) ||
-		    req->obj->len != 0) {
-			http_Unset(req->resp, H_Content_Length);
-			http_PrintfHeader(req->resp,
-			    "Content-Length: %zd", req->obj->len);
-		}
-	}
-
-	if (req->esi_level > 0) {
-		/* Included ESI object, always CHUNKED or EOF */
-		req->res_mode &= ~RES_LEN;
-		req->res_mode |= RES_ESI_CHILD;
+	} else {
+		req->res_mode |= RES_LEN;
+		http_Unset(req->resp, H_Content_Length);
+		http_PrintfHeader(req->resp,
+		    "Content-Length: %zd", req->obj->len);
 	}
 
 	if (cache_param->http_gzip_support && req->obj->gziped &&
@@ -314,9 +321,6 @@ V1D_Deliver(struct req *req, struct busyobj *bo)
 			v1d_dorange(req, bo, r);
 	}
 
-	if (req->res_mode & RES_ESI)
-		RFC2616_Weaken_Etag(req->resp);
-
 	WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_prev);
 
 	/*
diff --git a/bin/varnishtest/tests/r00730.vtc b/bin/varnishtest/tests/r00730.vtc
index bb416e8..67b9598 100644
--- a/bin/varnishtest/tests/r00730.vtc
+++ b/bin/varnishtest/tests/r00730.vtc
@@ -4,7 +4,7 @@ server s1 {
 	rxreq
 	txresp -bodylen 5
 	rxreq
-	txresp -bodylen 6
+	txresp -nolen -hdr "Content-Length: 6"
 } -start
 
 varnish v1 -vcl+backend {
diff --git a/bin/varnishtest/tests/r01612.vtc b/bin/varnishtest/tests/r01612.vtc
new file mode 100644
index 0000000..e66d3ec
--- /dev/null
+++ b/bin/varnishtest/tests/r01612.vtc
@@ -0,0 +1,52 @@
+varnishtest "Missing Content-Length/T-E on passed empty chunked responses."
+
+server s1 {
+	# Empty c-l response is OK.
+	rxreq
+	expect req.url == "/0"
+	txresp
+
+	# Nonzero chunked response is OK.
+	rxreq
+	expect req.url == "/1"
+	send "HTTP/1.1 200 OK\n"
+	send "Transfer-encoding: chunked\n"
+	send "\n"
+	chunkedlen 20
+	chunkedlen 0
+
+	# Empty chunked response is not.
+	rxreq
+	expect req.url == "/2"
+	send "HTTP/1.1 200 OK\n"
+	send "Transfer-encoding: chunked\n"
+	send "\n"
+	chunkedlen 0
+} -start
+
+varnish v1 -vcl+backend {
+	sub vcl_recv {
+		return (pass);
+	}
+	sub vcl_backend_response {
+		set beresp.do_stream = false;
+	}
+} -start
+
+
+client c1 {
+	txreq -url "/0"
+	rxresp
+	expect resp.bodylen == 0
+	expect resp.http.Content-Length == "0"
+
+	txreq -url "/1"
+	rxresp
+	expect resp.bodylen == 20
+	expect resp.http.Content-Length == "20"
+
+	txreq -url "/2"
+	rxresp
+	expect resp.bodylen == 0
+	expect resp.http.Content-Length == "0"
+} -run



More information about the varnish-commit mailing list