varnishvarnish-vclfastly

Varnish: Rewrite a URL if response is 404


I'm curious if there is a way rewrite a URL if response is a 404, in Varnish 2.1.5?

For example. I'd like to pull up a URL, which may or may not exist. If the URL doesn't exist, I'd like to do a URL rewrite and try the new URL instead.

I'm new to Varnish and don't completely understand the lifecycle of a request (if anyone knows a guy of article explaining this, please share).

I've tried setting some variables and request headers, and checking res.status but they seem to get lost someplace in the lifecycle and the page 404s anyways:

if (req.http.cookie ~ "lang_pref"
      && resp.status == 404
      && req.url ~ "^\/(en|fr|de)(\/.*)?$"
      ) {
    set resp.http.Location = "https://" req.http.host regsub(req.url, "^\/(en|fr|de)\/","/");
  }

The use case is for a translated site. Example

Website.com/french/page may or may not exist If /French/page responds with a 404 Then try /page instead If /page doesn't exist Then 404


Solution

  • I am writing this as an answer or it will look goofy as a comment. Keep in mind that 301 is permanently moved and 302 is temporarily moved.

    You can also adjust to use regex as you did in your post.

    sub vcl_recv {
        if (req.url ~ “^/old/page”) {
            return (synth(301, “/new/page”));
        }
        if (req.url ~ “^/this/oldPage”) {
            return (synth(302, “/this/newPage”));
        }
    }
    
    sub vcl_synth {
        if (resp.status == 301 || resp.status == 302) {
            set resp.http.location = resp.reason;
            set resp.reason = "Moved";
            return (deliver);
        }
    }
    

    UPDATE: To address comments.

    sub vcl_error { 
      if (obj.status == 404) { 
      set obj.status = 301; 
      set obj.http.Location = obj.response; 
      return (deliver);