Man_Pat
Man_Pat

Reputation: 117

Can varnish be used as a proxy to cache and serve third party resources?

I have a website that's using some third party scripts and images and they are key to having a fully functional website. But the site performance is taking a hit because these third party resources are having poor caching, compressing and cdn. And they do not even change for over a month.

I would like to use my varnish instance to cache these third party resources too JS, CSS and Images for at least a few hours and serve from my own server with optimization through my cloudflare.

Is this possible to do this with Varnish?

Upvotes: 2

Views: 761

Answers (1)

Joshua DeWald
Joshua DeWald

Reputation: 3229

Some additional considerations:

  • Can you servers handle whatever additional load would come from serving these assets (e.g. for one page view on your system, might there be 10-20 assets being served)?
  • What Cache-Control headers are being set, and do you want to ignore or override them for every asset
  • There is no guarantee that the resources would work correctly if served from another domain, as they may make assumptions about their relative paths or what domain they are being served on.

That said, there is no technical reason you couldn't set up a 'backend' for each and then proxy them using a URL pattern to detect which one to serve.

For instance, let's say you have a resource: http://someparty.com/assets/js/stuff.js

You could set up a backend:

backend thirdparty_someparty {
   .host = "someparty.com";
}

Then you might reference it in some form like:

<script src="//3p/someparty/assets/js/stuff.js"></script>

Then in your VCL:

sub vcl_recv {
   if (req.url ~ "^/3p/someparty") {
      set req.backend_hint = thirdparty_someparty;
      set req.url = regsub(req.url, "^/3p/someparty", "");
      // This way we don't override the Host for logging
      set req.http.HostOverride = "someparty.com";
   }
}

sub vcl_backend_fetch {
  if (bereq.http.HostOverride) {
     set bereq.http.Host = bereq.http.HostOverride;
  }
  unset bereq.http.HostOverride;
}

You mentioned that frequently the content doesn't change often. Depending on whether the origin is actually sending back headers corresponding to hours or days then you won't need to do anything, otherwise you will need to override the TTL in the response.

sub vcl_backend_response {
  if (bereq.http.Host == "someparty.com") {
     if (! beresp.uncacheable && beresp.ttl < 1h) {
        // Use your judgement here
        set beresp.ttl = 1h;
     }
  }
}

Hopefully that gets you started and helps a bit.

Upvotes: 5

Related Questions