Varnish Cache Plus

Edgestash 4

Varnish 4.1

Description

Edgestash is a realtime templating engine built inside of Varnish Cache Plus. Edgestash allows for JSON data to be composed into a response using Mustache syntax, ex: {{variable}}. Each response can be assigned its own JSON object for truly dynamic responses. JSON can either be fetched from a backend or generated via VCL and any number of JSONs can be assigned to a template.

An Edgestash template is fetched and compiled into response optimized byte code and then stored into cache. This byte code is then executed on delivery, efficiently streaming the response to the client using a zero-parse and zero-copy algorithm. JSON is also stored into cache as a fast search index.

Edgestash currently supports the full Mustache spec.

Edgestash is available in Varnish Cache Plus 4.1.6r2 and later.

This API applies to Varnish Cache Plus 4.1.

Edgestash 6.x API

Quick Start

vcl 4.0;

import edgestash;

backend default
{
  .host = "localhost";
  .port = "8080";
}

sub vcl_recv
{
  if (req.url ~ "esi=false") {
    set req.esi = false;
  }
}

sub vcl_backend_response
{
  if (bereq.url ~ "\.json$") {
    edgestash.index_json();
  } else if (bereq.url ~ "/edgestash/.*\.txt$") {
    edgestash.set_delimiter("[", "]");
    edgestash.parse_response();
  }
}

sub vcl_deliver
{
  if (req.url ~ "/edgestash/.*\.txt$" && edgestash.is_edgestash()) {
    edgestash.add_json_url(regsub(req.url, "\.txt$", ".json"));
    edgestash.execute();
  }

  if (edgestash.is_edgestash() || edgestash.is_json()) {
    set resp.http.X-edgestash = edgestash.version();
  }
}

VMOD

parse_response

VOID edgestash.parse_response()

  • Description

    Parse an Edgestash template into bytecode. Only can be used in vcl_backend_response.

  • Return value

    None

index_json

VOID edgestash.index_json()

  • Description

    Parse a JSON response. Optional. It enables storage of a fast JSON search index. If not invoked, JSON will be parsed on delivery, resulting in slower Edgestash assembly. Only can be used in vcl_backend_response.

  • Return value

    None

add_json_url

VOID add_json_url(STRING json_url, STRING json_host = "")

  • Description

    Include a JSON URL for Edgestash templating. Only can be used in vcl_deliver. JSON URL will execute back thru VCL with an esi_level + 1. Multiple JSON fetches will happen in parallel. Use index_json() on this URL to enable storage of a fast JSON search index. If this URL is JSON generated from an Edgestash template, use parse_response(). JSON will be searched and used in the order they are added, including add_json().

  • Return value

    None

    • json_url

      The JSON URL to use for Edgestash templating. URL must be supplied without the scheme and host.

    • json_host

      Optional. The Host header used for the subsequent JSON request.

add_json_url_csv

VOID add_json_url_csv(STRING json_urls, STRING prefix = "", STRING delimiter = ",", STRING json_host = "")

  • Description

    Parse a comma separated list of URLs and call add_json_url() for each. JSONs can be iterated using the following Edgestash syntax: {{ # . }} ... {{ / . }}

  • Return value

    None

    • json_urls

      Comma separated list of URLs.

    • prefix

      Optional. Prefix to prepend to each URL.

    • delimiter

      Delimiter used to parse json_urls. Single byte. Defauls to ,.

    • json_host

      Optional. The Host header used for the subsequent JSON request.

add_json

VOID add_json(STRING json)

  • Description

    Include a JSON string for Edgestash templating. Only can be used in vcl_deliver. JSON will be searched and used in the order they are added, including add_json_url().

  • Return value

    None

    • json

      The JSON string to use for Edgestash templating.

execute

VOID edgestash.execute(STRING json_url, BOOL do_gzip, STRING json)

  • Description

    Execute an Edgestash template. Only valid for responses which have been parsed with parse_response(). Partial includes will execute back thru VCL with an esi_level + 1. Only can be used in vcl_deliver.

  • Return value

    None

    • json_url

      DEPRECIATED. Please use add_json_url(). The JSON URL to use for Edgestash templating. URL must be supplied without the scheme and host. JSON URL will execute back thru VCL with an esi_level + 1. Use index_json() on this URL to enable storage of a fast JSON search index. If this URL is JSON generated from an Edgestash template, use parse_response().

    • do_gzip

      Gzip the response. Defaults to true.

    • json

      DEPRECIATED. Please use add_json(). A JSON string to use with the template.

set_delimiter

VOID edgestash.set_delimiter(STRING start, STRING end)

  • Description

    Set the initial Edgestash command delimiters. Only can be used in vcl_backend_response.

  • Return value

    None

    • start

      The starting Edgestash command delimiter. Default: {{

    • end

      The ending Edgestash command delimiter. Default: }}

is_edgestash

BOOL edgestash.is_edgestash()

  • Description

    Checks to see if parse_response() was called on this object and was successful in generating bytecode.

  • Return value

    True if Edgestash bytecode exists for this object, otherwise false.

is_json

BOOL edgestash.is_json()

  • Description

    Checks to see if index_json() was called on this object and was successful in generating an index.

  • Return value

    True if a json index exists for this object, otherwise false.

version

STRING edgestash.version()

  • Description

    Get the Edgestash implementation version.

  • Return value

    The Edgestash version.

req.esi

  • Description

    Boolean. Set to false to disable templating for this request. The Edgestash template will be delivered unprocessed. Useful when the raw template needs to be fetched into another cache or framework. Defaults to true. Can be used anywhere where req is valid.

Edgestash Syntax

{{variable}}

  • Description

    Variable, substitutes in the JSON value of variable. HTML is escaped, JSON is un-escaped, Ex:

    • < turns into &lt;

    • > turns into &gt;

    • \" turns into "

{{& variable}}

  • Description

    Unescaped variable, substitutes in the raw JSON value of variable. {{{variable}}} syntax is NOT supported. Variable supports dotted object and array syntax. HTML is untouched, JSON is untouched. Ex:

    • < is left as <

    • > is left as >

    • \" is left as \"

{{ # section}} {{/ section}}

  • Description

    A section block. If the value of section is not falsy, the section is executed, otherwise it is skipped. If the value is an object, it is used as context for the section. If the value is a non empty array, the section is repeated once for each element in the array and used as context (if the element is an object). If the value is a root object, all root JSON objects are iterated. Falsy values:

    • [], false, null

{{^ section}} {{/ section}}

  • Description

    An inverted section block. If the value of section is falsy, the section is executed, otherwise it is skipped. Falsy values:

    • [], false, null

{{! comment}}

  • Description

    Comment, these are ignored and removed. May contain newlines.

{{> /url}}

  • Description

    Partial, these are includes. The partial is executed back thru VCL with an esi_level + 1. If the partial is a template, the current JSON context is used (assuming no JSON was explicitly set for this template). A partial may only contain a URL without the scheme and host. You can use VCL to send the partial to a backend of your choosing. Ex:

    • {{> /site/templates/user.es}}

{{=sd ed=}}

  • Description

    Change the Edgestash command delimiter. Custom delimiter not contain whitespace or the equal sign. Ex:

    {{=[ ]=}}
    
    Edgestash variable: [variable]
    
    Untouched: {{variable}}
    

Notes

  • Preceding and trailing whitespace is allowed inside of all command syntax.
    Ex: {{ $ abc }} is equal to {{$abc}}

  • If the variable is not found, the variable is substituted with an empty string. If there is a section context, the variable is searched for in each parent until the root is hit. If multiple JSON files are used, files are searched in added order until the variable is found.

  • JSON is strictly parsed in full accordance to the official spec (json.org). Invalid JSON is equivalent to a null value.

  • If an Edgestash parsing error is encountered (unterminated variable, unterminated section, etc), the document is treated as plain text and templating will not happen.

Variables and Expressions

JSON Notation

  • Description

    Variables support dotted object and array syntax. Ex:

    {{variable}} - The variable value from the current JSON context.
    {{.}} - The current context.
    {{[0]}} - The first element of the current array context.
    {{name.begin}} - The begin value from the name object. If it doesn’t exist, the value name.begin.
    {{locations[2].country}} - The country value from the 3nd element (0 based index) of the locations array.

$first

  • Description

    Boolean. true if the current section context is the first element of an array, otherwise false. If the current section context is not an array or does not exist, value defaults to true.

$last

  • Description

    Boolean. true if the current section context is the last element of an array, otherwise false. If the current section context is not an array or does not exist, value defaults to true. Ex:

    [
      {{#array}}
        "{{value}}"
        {{^$last}},{{/$last}}
      {{/array}}
    ]
    

Example

  • GET /users/001

    • VCL
    import edgestash;
    
    sub vcl_backend_response
    {
      edgestash.index_json();
    }
    
    • Origin response code: 200

    • Origin response body

    {
      "name":"Chris Bar",
      "join_date": 2013
    }
    
  • GET /users/

    • VCL
    import edgestash;
    
    sub vcl_backend_response
    {
      edgestash.index_json();
    }
    
    • Origin response code: 404
  • GET /

    • VCL
    import edgestash;
    
    sub vcl_backend_response
    {
      edgestash.parse_response();
    }
      
    sub vcl_deliver
    {
      //X-userid header contains the userid
      edgestash.add_json_url("/users/" + req.http.X-userid);
      edgestash.execute();
    }
    
    • Origin response code: 200

    • Origin response body

    {{#name}}
      Welcome {{name}}! Member since {{join_date}}.
    {{/name}}
    {{^name}}
      Welcome Guest!
    {{/name}}
    
    • Varnish response (X-userid: 001)
    Welcome Chris Bar! Member since 2013.
    
    • Varnish response (X-userid:)
    Welcome Guest!