varnishvarnish-vclvarnish-4

Varnish: Making each API keys objects cache separately


I have Varnish 4 installation where I select a backend based on an API-key in the header of each request, such as (we are in vcl_recv):

if (req.url ~ "/content") {
    # Check for presence of X-Api-Key header
    if ((! req.http.X-Api-Key) || ((! req.http.X-Api-Key ~ "prod-") && (! req.http.X-Api-Key ~ "test-"))) {
        return(synth(403,"Access Denied - API key missing or invalid."));
    }
    if (req.http.X-Api-Key ~ "prod-") {
        set req.backend_hint = PROD.backend();
    }
    if (req.http.X-Api-Key ~ "test-") {
        set req.backend_hint = TEST.backend();
    }
}

However, objects fetched from the PROD backend can get delivered to requests to the TEST backend, if their TTL is not expired, and vice versa.

How do I make sure that content from each backend is isolated from the other?


Solution

  • This one is easy. Since you want the cache to vary by specific header, you should tell Varnish about it. So either make your backend send Vary: X-Api-Key (best route), or have Varnish hash on that header's value:

    sub vcl_hash {
        if (req.http.X-Api-Key) {
            hash_data(req.http.X-Api-Key);
        }
    }