diff --git a/bin/varnishd/cache/cache_req.c b/bin/varnishd/cache/cache_req.c index 101bf582c73..cb7567066d6 100644 --- a/bin/varnishd/cache/cache_req.c +++ b/bin/varnishd/cache/cache_req.c @@ -251,6 +251,7 @@ Req_Cleanup(struct sess *sp, struct worker *wrk, struct req *req) req->t_req = NAN; req->req_body_status = NULL; + req->uncacheable = 0; req->hash_always_miss = 0; req->hash_ignore_busy = 0; req->esi_level = 0; diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c index 1dc349b9986..f43a7e1be8e 100644 --- a/bin/varnishd/cache/cache_req_fsm.c +++ b/bin/varnishd/cache/cache_req_fsm.c @@ -871,6 +871,7 @@ cnt_recv_prep(struct req *req, const char *ci) req->hash_always_miss = 0; req->hash_ignore_busy = 0; req->client_identity = NULL; + req->uncacheable = 0; req->storage = NULL; } @@ -949,6 +950,10 @@ cnt_recv(struct worker *wrk, struct req *req) return (REQ_FSM_DONE); } + if (wrk->handling == VCL_RET_HASH && req->uncacheable) { + wrk->handling = VCL_RET_PASS; + } + recv_handling = wrk->handling; /* We wash the A-E header here for the sake of VRY */ diff --git a/bin/varnishtest/tests/c00105.vtc b/bin/varnishtest/tests/c00105.vtc new file mode 100644 index 00000000000..949b0edbad8 --- /dev/null +++ b/bin/varnishtest/tests/c00105.vtc @@ -0,0 +1,47 @@ +varnishtest "req.uncacheable" + +server s1 { + rxreq + txresp -body "1" + + rxreq + txresp -body "2" + + rxreq + txresp -body "3" +} -start + +varnish v1 -syntax 4.0 -arg "-smysteve=malloc,1m" -vcl+backend { + sub vcl_recv { + if (req.http.uncacheable) { + set req.uncacheable = true; + } + } +} -start + +client c1 { + # insert object in cache + txreq + rxresp + expect resp.body == "1" + + # hit the cached object + txreq + rxresp + expect resp.body == "1" + + # bypass the cache + txreq -hdr "uncacheable: true" + rxresp + expect resp.body == "2" + + # again + txreq -hdr "uncacheable: true" + rxresp + expect resp.body == "3" + + # hit the cached object + txreq + rxresp + expect resp.body == "1" +} -run diff --git a/doc/sphinx/reference/vcl_var.rst b/doc/sphinx/reference/vcl_var.rst index e1a673ec98f..46cb6af35cc 100644 --- a/doc/sphinx/reference/vcl_var.rst +++ b/doc/sphinx/reference/vcl_var.rst @@ -368,6 +368,22 @@ req.hash_always_miss This is useful to force-update the cache without invalidating existing entries in case the fetch fails. +req.uncacheable + + Type: BOOL + + Readable from: client + + Writable from: client + + Default: ``false``. + + Force a cache pass for this request, even if perfectly + good matching objects are in the cache. + + This allows to flag a request as uncacheable in ``vcl_recv`` without + immediately returning from the subroutine. + req.is_hitmiss Type: BOOL @@ -569,7 +585,8 @@ bereq.uncacheable Indicates whether this request is uncacheable due to a - `pass` in the client side or a hit on an hit-for-pass object. + `pass` or `req.uncacheable` in the client side or a hit on an + hit-for-pass object. bereq.connect_timeout diff --git a/include/tbl/req_flags.h b/include/tbl/req_flags.h index 2e826601cfe..c1b3c4e8588 100644 --- a/include/tbl/req_flags.h +++ b/include/tbl/req_flags.h @@ -41,6 +41,7 @@ REQ_FLAG(is_hitpass, 1, 0, "") REQ_FLAG(waitinglist, 0, 0, "") REQ_FLAG(want100cont, 0, 0, "") REQ_FLAG(late100cont, 0, 0, "") +REQ_FLAG(uncacheable, 1, 1, "") #undef REQ_FLAG /*lint -restore */