Writing VCL code

Whether you use snippets or custom VCL to write VCL code, the features available in the language are the same. This section summarises some of the most common VCL use cases.

TIP: Many common use cases for VCL are explored in our code examples gallery. The best practices guide also helps you understand how to avoid pitfalls and write safer, more secure edge code. Our fiddle tool also allows you to interactively write and execute VCL code without logging into Fastly, giving you space to experiment and test your ideas.

Manipulating headers

The set and unset statements allow for setting and unsetting HTTP headers on requests and responses. For example, in vcl_fetch, you could write:

sub vcl_fetch { ... }
Fastly VCL
set beresp.http.Cache-Control = "public, max-age=3600";
unset beresp.http.x-goog-request-id;

The {OBJ-NAME}.http.{HEADER-NAME} pattern is available for req, bereq, resp, beresp, and obj. See VCL variables for details of where each of these is available, but in general:

To add/remove headers on......use thisExample use cases
Client requestreq.http.{NAME} in vcl_recvRemove cookie header to strip credentials
Store data to refer to later in VCL
Backend requestbereq.http.{NAME} in vcl_miss and vcl_passAdd authentication headers
Backend responseberesp.http.{NAME} in vcl_fetchSet browser cache TTL
Remove superfluous origin response headers
Client responseresp.http.{NAME} in vcl_deliverSet cookies
Synthetic responseobj.http.{NAME} in vcl_errorSet the content-type of the synthetic response

URLs and query strings

The req.url variable contains the URL (path and query) being requested by the client, and is copied into bereq.url when making a request to a backend. The path and query can be separately accessed as req.url.path and req.url.qs. Consider using querystring.get and querystring.set to manipulate query parameters. querystring.filter can remove unwanted query parameters:

Using regular expressions on the URL path is a common way to route requests to different backends, by setting req.backend:

Cookies

Since the Cookie header is a comma-delimited list of individual cookies, you can access a named cookie using subfield accessor syntax. Often this is usefully combined with a regular expression match to extract parts of a structured cookie value. For example, if you have a cookie called auth, which has a value such as 52b93cff.165826435.d783dad8-ebb9-4475-b6fb-68ce83f90f12, you could use the following VCL to isolate the auth cookie, and then extract the various parts of it into distinct HTTP headers:

sub vcl_recv { ... }
Fastly VCL
if (req.http.cookie:auth ~ "^([0-9a-f]+).(\d+).([\w-]+)$") {
set req.http.Auth-SessionID = re.group.1;
set req.http.Auth-CreditCount = re.group.2;
set req.http.Auth-DisplayName = re.group.3;
}

To write cookies, construct a Set-Cookie header on the client response, normally in vcl_deliver. Using set will overwrite any existing header with the same name, so if you may be setting multiple cookies in the same response, use add instead. It's also wise, when setting cookies on a response, to prevent the client or any downstream entity from caching it.

sub vcl_deliver { ... }
Fastly VCL
add resp.http.set-cookie = "auth=52b93cff.165826435.d783dad8-ebb9-4475-b6fb-68ce83f90f12; max-age=86400; path=/";
set resp.http.cache-control = "private, no-store";

Logging

Fastly supports logging data to a variety of specific vendors and generic endpoints. In VCL, you can emit a log message from anywhere in your VCL code using the log statement:

log "syslog " + req.service_id + " my-log-endpoint :: " + req.url;

All log statements in VCL take the form log "syslog {service_id} {log_endpoint_name} :: {log_message}. For more information on configuring log endpoints, and how to use them, see our Logging overview.

Controlling the cache

Fastly respects freshness-related HTTP headers sent in origin responses, such as Cache-Control, Last-Modified, and Expires. You can override this behavior using VCL in vcl_fetch, by setting the values of beresp.ttl, beresp.stale_while_revalidate, and beresp.stale_if_error.

sub vcl_fetch { ... }
Fastly VCL
set beresp.ttl = 30m;

Regardless of HTTP headers or explicit instructions in VCL, the cache may be disabled if the response has an HTTP status that does not support caching. A 200 (OK) response is considered cacheable, while a 500 (Internal Server Error) is not. You can change this decision by setting beresp.cacheable. For more information, read our HTTP semantics overview.

IMPORTANT: Setting the value of headers such as Cache-Control using VCL will not have any affect on whether or for how long the response is cached by Fastly (use beresp.ttl instead), but setting a Cache-Control header on a response is a good way to control whether the response is cached on the end user's device. To disable caching entirely, execute a return(pass) from vcl_recv or vcl_fetch. Doing so in vcl_recv offers better performance because it allows us to skip request collapsing.

Synthetic responses

When an error occurs during request or response processing, the vcl_error subroutine will be executed, and an HTTP response will be created within Fastly. You can trigger this behavior explicitly using the error statement:

error 601;

If you trigger an error manually as shown above, pass a number in the 600-699 range (learn more about HTTP statuses used by Fastly). Then catch that error number in vcl_error:

sub vcl_error { ... }
Fastly VCL
if (obj.status == 601) {
set obj.status = 200;
set obj.http.content-type = "text/plain";
synthetic "OK";
return(deliver);
}

When vcl_error is executed, a new, 'synthetic' HTTP response is created and represented by obj. Use set with obj.http.{NAME} and obj.status to set the headers and response status of the object, and the synthetic statement to populate the response body.