[master] 97434c7 Handle Range requests on streaming objects better.

Poul-Henning Kamp phk at FreeBSD.org
Mon May 4 23:15:55 CEST 2015


commit 97434c7cef70d99533f1fb7f78419dd5c9d36d23
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon May 4 21:13:36 2015 +0000

    Handle Range requests on streaming objects better.
    
    If the client sends [LO]-HI range, we trust it knows something we don't (yet),
    and do the Range request.  If we later ran out of data, we close the session.
    
    Other range requests on streaming objects are ignored.
    
    Fixes: #1506
    Fixes: #1618

diff --git a/bin/varnishd/cache/cache_range.c b/bin/varnishd/cache/cache_range.c
index 7562095..31ec81e 100644
--- a/bin/varnishd/cache/cache_range.c
+++ b/bin/varnishd/cache/cache_range.c
@@ -56,11 +56,14 @@ vrg_range_bytes(struct req *req, enum vdp_action act, void **priv,
 	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
 	if (act == VDP_INIT)
 		return (0);
+	CAST_OBJ_NOTNULL(vrg_priv, *priv, VRG_PRIV_MAGIC);
 	if (act == VDP_FINI) {
-		*priv = NULL;
+		if (vrg_priv->range_off < vrg_priv->range_high)
+			SES_Close(req->sp, SC_RANGE_SHORT);
+		*priv = NULL;	/* struct on ws, no need to free */
 		return (0);
 	}
-	CAST_OBJ_NOTNULL(vrg_priv, *priv, VRG_PRIV_MAGIC);
+
 	l = vrg_priv->range_low - vrg_priv->range_off;
 	if (l > 0) {
 		if (l > len)
@@ -126,19 +129,29 @@ vrg_dorange(struct req *req, const struct busyobj *bo, ssize_t len,
 		return (__LINE__);
 
 	if (!has_low) {
+		if (bo != NULL)
+			return (0);		// Allow 200 response
 		if (high == 0)
 			return (__LINE__);
 		low = len - high;
 		if (low < 0)
 			low = 0;
 		high = len - 1;
-	} else if (high >= len || !has_high)
+	} else if (bo == NULL && (high >= len || !has_high))
 		high = len - 1;
+	else if (!has_high)
+		return (0);			// Allow 200 response
+	/*
+	 * else (bo != NULL) {
+	 *    We assume that the client knows what it's doing and trust
+	 *    that both low and high make sense.
+	 * }
+	 */
 
 	if (high < low)
 		return (__LINE__);
 
-	if (low >= len)
+	if (bo == NULL && low >= len)
 		return (__LINE__);
 
 	http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd",
diff --git a/bin/varnishtest/tests/r01506.vtc b/bin/varnishtest/tests/r01506.vtc
index 09a8db0..f2bb5b2 100644
--- a/bin/varnishtest/tests/r01506.vtc
+++ b/bin/varnishtest/tests/r01506.vtc
@@ -1,45 +1,72 @@
-varnishtest "Streaming of C-L header from backend"
+varnishtest "range requests on streamed response"
 
-server s1 {
+server s1 -repeat 4 {
 	rxreq
-	txresp -nolen -hdr "Content-Length: 020"
-	send "0123456789"
+	txresp -nolen \
+	    -hdr "Transfer-Encoding: chunked" \
+	    -hdr "Connection: close"
+	send "11\r\n0_23456789abcdef\n"
+	send "11\r\n1_23456789abcdef\n"
+	send "11\r\n2_23456789abcdef\n"
+	send "11\r\n3_23456789abcdef\n"
 	sema r1 sync 2
-	send "0123456789"
+	send "11\r\n4_23456789abcdef\n"
+	send "11\r\n5_23456789abcdef\n"
+	send "11\r\n6_23456789abcdef\n"
+	send "11\r\n7_23456789abcdef\n"
+	chunkedlen 0
 
-	rxreq
-	txresp -nolen -hdr "Content-Length: 010"
-	sema r2 sync 2
-	send "0123456789"
 } -start
 
-varnish v1 -vcl+backend {
+varnish v1 -vcl+backend {} -start
+
+varnish v1 -cliok "param.set debug +syncvsl"
 
-	sub vcl_backend_response {
-		if (bereq.url == "/2") {
-			set beresp.do_gzip = true;
-		}
-	}
-} -start -cliok "param.set debug +syncvsl" -cliok "param.set debug +flush_head"
+logexpect l1 -v v1 -g session {
+	expect 0 1000	Begin		sess
+	expect * =	SessClose	RANGE_SHORT
+} -start
 
 client c1 {
-	txreq
+	txreq -url /1 -hdr "Range: bytes=17-101"
+	rxresphdrs
+	expect resp.status == 206
+	expect resp.http.content-length == 85
+	sema r1 sync 2
+	rxrespbody
+	expect resp.bodylen == 85
+	delay .1
+
+	# We cannot do tail-ranges when streaming
+	txreq -url /2 -hdr "Range: bytes=-10"
 	rxresphdrs
-	expect resp.http.content-length == "020"
+	expect resp.status == 200
+	expect resp.http.Transfer-Encoding == chunked
 	sema r1 sync 2
 	rxrespbody
-	expect resp.body == "01234567890123456789"
+	expect resp.bodylen == 136
 	delay .1
 
-	txreq -url "/2"
+	# We cannot do open-ranges when streaming
+	txreq -url /3 -hdr "Range: bytes=17-"
 	rxresphdrs
-	expect resp.http.content-length == "<undef>"
-	sema r2 sync 2
+	expect resp.status == 200
+	expect resp.http.Transfer-Encoding == chunked
+	sema r1 sync 2
 	rxrespbody
-	expect resp.body == "0123456789"
+	expect resp.bodylen == 136
 	delay .1
 
-	txreq -url "/2"
-	rxresp
-	expect resp.http.content-length == "10"
+	# Invalid range
+	txreq -url /4 -hdr "Range: bytes=102-200"
+	rxresphdrs
+	expect resp.status == 206
+	expect resp.http.content-length == 99
+	sema r1 sync 2
+	recv 34
+	delay .3
+	expect_close
 } -run
+
+varnish v1 -expect sc_range_short == 1
+logexpect l1 -wait



More information about the varnish-commit mailing list