[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