1
votes

we recently have put Varnish in front of our Drupal because the server was suffering heavy load and we are very pleased in general.

The only problem remaining is that we sometimes have an infinite redirection loop in the cached data. We have found this through our HTTP-Monitoring. We check the front page every minute. The page in the cache sometimes contains the full front page, but with a Location header set, that sends the user to the front page again.

We are not quite sure what could cause this, but also have no clue on how could track this down. Of course, the best way to handle this would be on the drupal side, but we can't really tell why this does happen.

Is there a way to log the cases when this happens? Or is it possible to detect this in varnish and mark the current cache content as invalid?

Of course, we don't want to always pass intentional redirects to the origin server, but the ones that would cause an infinite loop.

I hope to hear some ideas how we can further track this down. Many thank in advance for all kinds of hints.

2

2 Answers

2
votes

I have found a workaround for this:

sub vcl_fetch {
  // Fix a strange problem: HTTP 301 redirects to the same page sometimes go in$
  if (beresp.http.Location == "http://" + req.http.host + req.url) {
    if (req.restarts > 2) {
      unset beresp.http.Location;
      #set beresp.http.X-Restarts = req.restarts;
    } else {
      return (restart);
    }
  }
}

I give the backend a second (and thirhd) chance to return a proper page. If that fails as well, the Location header is removed. This works, because the proper page is served with just an additional invalid Location header.

0
votes

The accepted answer by @philip updated for Varnish 4:

sub vcl_backend_response {

#Fix a strange problem: HTTP 301 redirects to the same page sometimes go in$
if (beresp.http.Location == "http://" + bereq.http.host + bereq.url) {
    if (bereq.retries > 2) {
      unset beresp.http.Location;
      #set beresp.http.X-Restarts = bereq.retries;
    } else {
      return (retry);
    }
}

}