optimizationvarnishvarnish-vcl

Varnish, custom subroutine with early exit


I'm new to Varnish. While editing our backend selector subroutine, I found myself looking for early return pattern in Varnish configuration files.

sub select_backend {
  if (req.http.host ~ "tracking\..*") {
    set req.backend = tracking;
  }

  if (req.http.host ~ "myapp1.domain.com") {
    if (req.url ~ "^/insecure/path") {
      error 403 "Forbidden";
    }
    set req.backend = app1;
  }

  if (req.http.host ~ "myapp2.domain.com") {
    set req.backend = app2;
  }
}

sub vcl_recv {
  // other stuffs
  call select_backend;
}

Without proper return/exit statement there is a risk (as the file get more and more complex) to change twice the backend. Is it possible to use a early return pattern to avoid that ? If not, how do I avoid the if/elseif pattern without wasting performance ?


Solution

  • Currently there is no good way to do this, as the Syntax part of VCL Basics explains:

    The "return" statement of VCL returns control from the VCL state engine to Varnish. If you define your own function and call it from one of the default functions, typing "return(foo)" will not return execution from your custom function to the default function, but return execution from VCL to Varnish. That is why we say that VCL has terminating statements, not traditional return values.

    Some other people has had similar needs and the recommendation has been:

      if (req.http.host ~ "tracking\..*") {
        set req.backend = tracking;
      } elsif (req.http.host ~ "myapp1.domain.com") {
        if (req.url ~ "^/insecure/path") {
          error 403 "Forbidden";
        }
        set req.backend = app1;
      } elsif (req.http.host ~ "myapp2.domain.com") {
        set req.backend = app2;
      }
    

    If you keep the pattern if .. elsif there should be no opportunities to set the backed two times. If you keep separate if { } blocks you can have this happening.