From 0a37f352a621b41ea7d0c7574255746c0fd0fc46 Mon Sep 17 00:00:00 2001 From: Ludovic Muller Date: Tue, 23 Apr 2024 17:48:12 +0200 Subject: [PATCH] feat(purge): purge cache entry using PURGE HTTP method --- .changeset/violet-lizards-chew.md | 5 +++++ config/default.vcl | 26 ++++++++++++++++---------- test/docker-compose.yaml | 2 -- test/run.sh | 20 ++++++++++++++++---- 4 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 .changeset/violet-lizards-chew.md diff --git a/.changeset/violet-lizards-chew.md b/.changeset/violet-lizards-chew.md new file mode 100644 index 0000000..1afd9fd --- /dev/null +++ b/.changeset/violet-lizards-chew.md @@ -0,0 +1,5 @@ +--- +"varnish-post": minor +--- + +Support `PURGE` method to purge the cache diff --git a/config/default.vcl b/config/default.vcl index 6e7a799..ccf2613 100644 --- a/config/default.vcl +++ b/config/default.vcl @@ -3,14 +3,14 @@ vcl 4.1; import std; import bodyaccess; -# this is the backend that should be cached +# Backend server that should be cached backend default { .host = "$BACKEND_HOST"; .port = "$BACKEND_PORT"; .first_byte_timeout = $BACKEND_FIRST_BYTE_TIMEOUT; } -# remove cookies from response +# Remove cookies and other non-cache-friendly headers from the backend response sub vcl_backend_response { if (beresp.http.Cache-Control) { unset beresp.http.Cache-Control; @@ -22,20 +22,25 @@ sub vcl_backend_response { set beresp.ttl = $CACHE_TTL; - # handle errors + # Decide not to cache error responses if ($DISABLE_ERROR_CACHING && beresp.status >= 400) { - # send requests directly to the backend for the next ttl period set beresp.ttl = $DISABLE_ERROR_CACHING_TTL; set beresp.uncacheable = true; return (deliver); } } -# remove incoming cookies and allow caching POST requests +# Handles incoming requests and removes incoming cookies sub vcl_recv { unset req.http.X-Body-Len; unset req.http.cookie; + # Handle PURGE requests + if (req.method == "PURGE") { + return (purge); + } + + # Caching POST requests by caching the request body if (req.method == "POST") { std.cache_req_body($BODY_SIZE); set req.http.X-Body-Len = bodyaccess.len_req_body(); @@ -52,12 +57,12 @@ sub vcl_recv { return (hash); } -# https://docs.varnish-software.com/tutorials/caching-post-requests/#step-3-change-the-hashing-function +# Alter the hashing method to include POST bodies +# See: https://docs.varnish-software.com/tutorials/caching-post-requests/#step-3-change-the-hashing-function sub vcl_hash { hash_data(req.http.Authorization); hash_data(req.url); - # to cache POST and PUT requests if (req.http.X-Body-Len) { bodyaccess.hash_req_body(); } else { @@ -67,16 +72,17 @@ sub vcl_hash { return (lookup); } -# https://docs.varnish-software.com/tutorials/caching-post-requests/#step-4-make-sure-the-backend-gets-a-post-request +# Adjust the request method in the backend fetch phase +# See: https://docs.varnish-software.com/tutorials/caching-post-requests/#step-4-make-sure-the-backend-gets-a-post-request sub vcl_backend_fetch { if (bereq.http.X-Body-Len) { set bereq.method = "POST"; } } -# add a header to see if it was a cache miss or a cache hit +# Indicate whether the response was served from cache or not +# See: https://happyculture.coop/blog/varnish-4-comment-savoir-si-votre-page-vient-du-cache sub vcl_deliver { - # https://happyculture.coop/blog/varnish-4-comment-savoir-si-votre-page-vient-du-cache if (resp.http.X-Varnish ~ "[0-9]+ +[0-9]+") { set resp.http.X-Cache = "HIT"; } else { diff --git a/test/docker-compose.yaml b/test/docker-compose.yaml index 6a0dbe5..6c1e60e 100644 --- a/test/docker-compose.yaml +++ b/test/docker-compose.yaml @@ -1,5 +1,3 @@ -version: "3" - services: backend: build: ./app diff --git a/test/run.sh b/test/run.sh index f9d69b7..f405d48 100755 --- a/test/run.sh +++ b/test/run.sh @@ -4,8 +4,8 @@ BACKEND_ENDPOINT="http://localhost:8080" CACHED_ENDPOINT="http://localhost:8081" # build and start the stack -docker-compose build -docker-compose up -d +docker compose build +docker compose up -d # Some useful functions @@ -13,7 +13,7 @@ docker-compose up -d ## $1: error message to display error () { echo "ERROR: $1" >&2 - docker-compose down + docker compose down exit 1 } @@ -220,8 +220,20 @@ if [ "${res1}" -ge "${res2}" ]; then error "timestamp is not increasing" fi +info "Check if we can purge a cache entry…" +sleep 3 +# do a request after TTL to invalidate the cache +res_tmp=$(fetch_time "${CACHED_ENDPOINT}") +res1=$(fetch_time "${CACHED_ENDPOINT}") +sleep 1 +curl -sL -X PURGE "${CACHED_ENDPOINT}" >/dev/null +res2=$(fetch_time "${CACHED_ENDPOINT}") +if [ "${res1}" -eq "${res2}" ]; then + error "cache was not purged" +fi + # If we are at this point, no test failed info "All tests passed :)" -docker-compose down +docker compose down exit 0