Search code examples
varnishvarnish-vcl

Varnish serves wrong files


i'm using a varnish 3 behind a nging to proxy multiple sites into one domain. The basic setup works fine but I now have a problem with varnish serving the wrong files if the filename already exists in it's cache. Basically all I do in my default.vcl is this:

   if(req.url ~ "^/foo1") {
        set req.backend = foo1;
        set req.url = regsub(req.url, "^/foo1/", "/");
    }
    else if(req.url ~ "^/foo2") {
        set req.backend = foo2;
        set req.url = regsub(req.url, "^/foo2/", "/");
    }

If I now call /foo1/index.html, /foo2/index.html will serve the same file. After a restart of varnish and a call of /foo2/index.html, /foo1/index.html will serve foo2's index.html.

As far as I found out this is an issue with the creation of the hash which does not respect the used backend but only the url (after shortening) and the domain:

    11 VCL_call     c hash
    11 Hash         c /index.html
    11 Hash         c mydomain

I solved this issue for now by altering my vcl_hash to also use the backend but I'm sure there must be a better, more convenient way:

    sub vcl_hash {
      hash_data(req.url);
      hash_data(req.backend);
    }

Any hint would be appreciated, thank you very much!


Solution

  • You have two different ways of doing this. First one, is to do what you suggested by adding extra values (e.g. req.backend) in vcl_hash.

    sub vcl_hash {
       hash_data(req.url);
       hash_data(req.backend);
    }
    

    Second way, is to not update req in vcl_recv, but only bereq in vcl_miss/pass.

    sub vcl_urlrewrite {
        if(req.url ~ "^/foo1") {
            set bereq.url = regsub(req.url, "^/foo1/", "/");
        }
        else if(req.url ~ "^/foo2") {
            set bereq.url = regsub(req.url, "^/foo2/", "/");
        }
    }
    sub vcl_miss {
        call vcl_urlrewrite;
    }
    sub vcl_pass {
        call vcl_urlrewrite;
    }
    sub vcl_pipe {
        call vcl_urlrewrite;
    }
    

    This second approach requires more VCL but it comes with advantages as well. For example, when analyzing logs with varnishlog, you can see the vanilla request (c column), and also the updated backend request (b column).

    $ varnishlog /any-options-here/
    (..)
       xx RxURL        c /foo1/index.html
    (..)
       xx TxURL        c /index.html
    (..)
    $