This article will describe a configuration example based on a couple of rather popular VMODs: http and goto. Varnish Plus is shipped with dynamic backend support, which simplifies integration and gives the following benefits when used with the policy engine:
vcl 4.0;
import http;
import goto;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Prepare and send the policy request
http.init(0);
http.req_copy_headers(0);
http.req_unset_header(0, "content-length");
http.req_unset_header(0, "connection");
http.req_set_method(0, req.method);
http.req_set_url(0, "http://localhost:8088" + req.url);
http.req_send(0);
http.resp_wait(0);
# Reject requests not accepted by the Policy Engine
if (http.resp_get_status(0) != 200) {
return(synth(http.resp_get_status(0)));
}
# Prepare the backend request
if (http.resp_get_header(0, "x-upstream-url", "") != "") {
set req.http.x-upstream-url = http.resp_get_header(0, "x-upstream-url", "");
}
if (http.resp_get_header(0, "x-upstream-path", "") != "") {
set req.url = http.resp_get_header(0, "x-upstream-path", "");
}
if (http.resp_get_header(0, "x-upstream-preserve-host", "") == "false") {
# The host header should not be preserved
set req.http.host = http.resp_get_header(0, "x-upstream-host", "");
}
}
sub vcl_backend_fetch {
# Use goto to connect to the backend if we got upstream information
if (bereq.http.x-upstream-url) {
set bereq.backend =
goto.backend(bereq.http.x-upstream-url);
}
}
sub pe_response_headers {
# Let the client know about the rate limit
if (http.resp_get_header(0, "x-ratelimit-limit", "") != "") {
set resp.http.x-ratelimit-limit =
http.resp_get_header(0, "x-ratelimit-limit", "");
}
if (http.resp_get_header(0, "x-ratelimit-remaining", "") != "") {
set resp.http.x-ratelimit-remaining =
http.resp_get_header(0, "x-ratelimit-remaining", "");
}
if (http.resp_get_header(0, "x-ratelimit-reset", "") != "") {
set resp.http.x-ratelimit-reset =
http.resp_get_header(0, "x-ratelimit-reset", "");
}
if (http.resp_get_header(0, "www-authenticate", "") != "") {
set resp.http.www-authenticate =
http.resp_get_header(0, "www-authenticate", "");
}
}
sub vcl_synth {
call pe_response_headers;
}
sub vcl_deliver {
call pe_response_headers;
}
Varnish Custom Statistics can be used to gather interesting statistics from the policy engine setup. The following VCL configuration can be appended to the configuration above to gather policy engine-specific statistics:
vcl 4.0;
import std;
import http;
sub vcl_recv {
if (http.resp_get_header(0, "x-endpoint", "") != "") {
std.log("vcs-key:ENDPOINT/" + http.resp_get_header(0, "x-endpoint", ""));
std.log("vcs-key:ENDPOINT/" + http.resp_get_header(0, "x-endpoint", "") + "/STATUS/" + http.resp_get_status(0));
if (http.resp_get_header(0, "x-auth-user", "") != "") {
std.log("vcs-key:CONSUMER/" + http.resp_get_header(0, "x-auth-user", ""));
std.log("vcs-key:CONSUMER/" + http.resp_get_header(0, "x-auth-user", "") + "/STATUS/" + http.resp_get_status(0));
std.log("vcs-key:CONSUMER/" + http.resp_get_header(0, "x-auth-user", "") + "/ENDPOINT/" + http.resp_get_header(0, "x-endpoint", ""));
std.log("vcs-key:ENDPOINT/" + http.resp_get_header(0, "x-endpoint", "") + "/CONSUMER/" + http.resp_get_header(0, "x-auth-user", ""));
}
}
}
These few lines of VCL configuration will produce statistics, such as (but not limited to) the number of requests, time to first byte, request size, response size, backend request size, backend response size and cache miss count - broken down by: