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:
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 this | Example use cases |
---|---|---|
Client request | req.http.{NAME} in vcl_recv | Remove cookie header to strip credentials Store data to refer to later in VCL |
Backend request | bereq.http.{NAME} in vcl_miss and vcl_pass | Add authentication headers |
Backend response | beresp.http.{NAME} in vcl_fetch | Set browser cache TTL Remove superfluous origin response headers |
Client response | resp.http.{NAME} in vcl_deliver | Set cookies |
Synthetic response | obj.http.{NAME} in vcl_error | Set 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:
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.
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
.
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
:
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.