kdutreo
kdutreo

Reputation: 5

varnish 4 - abandon, vcl_synth, and restarting requests with new headers

I've already asked and received an awesome answer about how to get an error from the backend to force serving from stale cache (grace) found here: varnish 4: serve graced object if beresp.status is an error?

but now that logic needs an extra step: i include the following code currently

sub vcl_backend_fetch {
  if (bereq.retries == 0) {
    unset bereq.http.X-Varnish-Backend-5xx;
    unset bereq.http.X-Varnish-Backend-206;
  } else {
    if (bereq.http.X-Varnish-Backend-5xx) {
      return (abandon);
    }
    if (bereq.http.X-Varnish-Backend-206) {
      return (abandon);
    }
  }
}

sub vcl_synth {
  if (resp.status == 503 &&
    req.method != "POST" &&
    !req.http.X-Varnish-Restarted-5xx) {
    set req.http.X-Varnish-Restarted-5xx = "1";
    return (restart);
  }

  if (resp.status == 503 &&
    req.method != "POST" &&
    !req.http.X-Varnish-Restarted-206) {
    set req.http.X-Varnish-Restarted-206 = "1";
    return (restart);
  }

}

obviously the second if statement in the vcl_synth is virtually identical to the first one, with the exception of the header it's looking for. I need to differentiate the 206 to restart with a different request header, but I am not sure how. the issue is that, if the backend returns a 206, the rest of the logic abandons the backend fetch (which hands off to vcl_synth with a 503), and vcl_synth restarts the request to force serving graced cached objects. however, if there's no graced cache object to return to the user, then the user sees a 503 instead of a 206.

Before realizing that this line of thinking was not possible, i tried to have vcl_backend_fetch return a synth(206), so that vcl_synth could use resp.status to differentiate, and add a different request header before restarting the request. then i would be able to look for that header in vcl_miss, and if it's there, i could restart the whole request a second time, and force it to serve the 206 from the usual backend.

TL;DR: how do I differentiate two different cases in a vcl_backend_fetch abandon, to get vcl_synth to restart the request with two different headers?

Upvotes: 0

Views: 2393

Answers (1)

Carlos Abalde
Carlos Abalde

Reputation: 1087

I'm pretty sure it's not possible to do anything in vcl_backend_fetch in order to abandon the request and transfer some kind of flag to vcl_synth.

I'm not sure if I've completely understood your use case, but it seems that would need something like:

sub vcl_synth {
    if (resp.status == 503 &&
        req.method != "POST" &&
        !req.http.X-Varnish-Restarted-5xx) {
        # Let's restart the request for the first time and try to 
        # serve grace content. This could select an always-sick
        # backend during vcl_recv.
        set req.http.X-Varnish-Restarted-5xx = "1";
        return (restart);
    }

    if (resp.status == 503 &&
        req.method != "POST" &&
        req.http.X-Varnish-Restarted-5xx &&
        !req.http.X-Varnish-Restarted-206) {
        # Grace content was not available after the first restart. Let's 
        # restart again the request and try to serve content using some
        # other backend.
        set req.http.X-Varnish-Restarted-206 = "1";
        return (restart);
    }
}

Upvotes: 0

Related Questions