[master] 649ad2ba7 add if-range logic
guillaume quintard
gquintard at users.noreply.github.com
Mon Nov 11 17:22:06 UTC 2019
commit 649ad2ba79f44fb0213331e8692361d1f6aa0daa
Author: Guillaume Quintard <guillaume at varnish-software.com>
Date: Sat Nov 2 18:06:16 2019 -0700
add if-range logic
diff --git a/bin/varnishd/cache/cache_range.c b/bin/varnishd/cache/cache_range.c
index ab96954fd..dcbfeef49 100644
--- a/bin/varnishd/cache/cache_range.c
+++ b/bin/varnishd/cache/cache_range.c
@@ -33,6 +33,7 @@
#include "cache_filter.h"
#include "vct.h"
+#include <vtim.h>
/*--------------------------------------------------------------------*/
@@ -180,6 +181,58 @@ vrg_dorange(struct req *req, const char *r, void **priv)
return (NULL);
}
+/*
+ * return 1 if range should be observed, based on if-range value
+ * if-range can either be a date or an ETag [RFC7233 3.2 p8]
+ */
+static int
+vrg_ifrange(struct req *req)
+{
+ const char *p, *e;
+ vtim_real ims, lm, d;
+
+ if (!http_GetHdr(req->http, H_If_Range, &p)) // rfc7233,l,455,456
+ return (1);
+
+ /* strong validation needed */
+ if (p[0] == 'W' && p[1] == '/') // rfc7233,l,500,501
+ return (0);
+
+ /* ETag */
+ if (p[0] == '"') { // rfc7233,l,512,514
+ if (!http_GetHdr(req->resp, H_ETag, &e))
+ return (0);
+ if ((e[0] == 'W' && e[1] == '/')) // rfc7232,l,547,548
+ return (0);
+ return (strcmp(p, e) == 0); // rfc7232,l,548,548
+ }
+
+ /* assume date, strong check [RFC7232 2.2.2 p7] */
+ if (!(ims = VTIM_parse(p))) // rfc7233,l,502,512
+ return (0);
+
+ /* the response needs a Date */
+ // rfc7232 fc7232,l,439,440
+ if (!http_GetHdr(req->resp, H_Date, &p) || !(d = VTIM_parse(p)))
+ return (0);
+
+ /* grab the Last Modified value */
+ if (!http_GetHdr(req->resp, H_Last_Modified, &p))
+ return (0);
+
+ lm = VTIM_parse(p);
+ if (!lm)
+ return (0);
+
+ /* Last Modified must be 60 seconds older than Date */
+ if (lm > d + 60) // rfc7232,l,442,443
+ return (0);
+
+ if (lm != ims) // rfc7233,l,455,456
+ return (0);
+ return (1);
+}
+
static int v_matchproto_(vdp_init_f)
vrg_range_init(struct req *req, void **priv)
{
@@ -187,6 +240,8 @@ vrg_range_init(struct req *req, void **priv)
const char *err;
assert(http_GetHdr(req->http, H_Range, &r));
+ if (!vrg_ifrange(req)) // rfc7233,l,455,456
+ return (1);
err = vrg_dorange(req, r, priv);
if (err == NULL)
return (*priv == NULL ? 1 : 0);
diff --git a/bin/varnishtest/tests/c00100.vtc b/bin/varnishtest/tests/c00100.vtc
new file mode 100644
index 000000000..ebf690430
--- /dev/null
+++ b/bin/varnishtest/tests/c00100.vtc
@@ -0,0 +1,88 @@
+varnishtest "if-range header"
+
+server s1 {
+ rxreq
+ txresp -hdr {etag: "foo"} -hdr "last-modified: Wed, 21 Oct 2015 07:28:00 GMT" -bodylen 16
+
+ rxreq
+ txresp -bodylen 16
+} -start
+
+varnish v1 -vcl+backend {} -start
+
+client c1 {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # if-range, but no range
+ txreq -hdr {if-range: "foo"}
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # non-matching etag if-range
+ txreq -hdr {if-range: "fooled"} -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # matching etag if-range
+ txreq -hdr {if-range: "foo"} -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 206
+ expect resp.bodylen == 5
+
+ # non-matching date if-range (past)
+ txreq -hdr "if-range: Wed, 21 Oct 2015 07:18:00 GMT" -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # non-matching date if-range (future)
+ txreq -hdr "if-range: Wed, 21 Oct 2015 07:38:00 GMT" -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # matching etag if-range
+ txreq -hdr "if-range: Wed, 21 Oct 2015 07:28:00 GMT" -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 206
+ expect resp.bodylen == 5
+}-run
+
+varnish v1 -cliok "ban obj.status != x"
+
+# no etag/LM header
+client c1 {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # non-matching etag if-range
+ txreq -hdr {if-range: "fooled"} -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # matching etag if-range
+ txreq -hdr {if-range: "foo"} -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # non-matching date if-range (past)
+ txreq -hdr "if-range: Wed, 21 Oct 2015 07:18:00 GMT" -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+
+ # non-matching date if-range (future)
+ txreq -hdr "if-range: Wed, 21 Oct 2015 07:38:00 GMT" -hdr "range: bytes=5-9"
+ rxresp
+ expect resp.status == 200
+ expect resp.bodylen == 16
+} -run
More information about the varnish-commit
mailing list