Getting started
Basics
Domains & Origins
Performance

Configuration
Basics
Conditions
Dictionaries
Domains & Origins
Request settings
Cache settings
Headers
Responses
Performance
Purging
Custom VCL
Image optimization
Video

Security
Access Control Lists
Monitoring and testing
Securing communications
Security measures
TLS
Web Application Firewall

Integrations
Logging endpoints
Non-Fastly services

Diagnostics
Streaming logs
Debugging techniques
Common errors

Account info
Account management
Billing
User access and control

Reference

    Working with Edge Dictionaries using the API

      Last updated January 18, 2019

    Edge Dictionaries allow you to create logic that doesn't need to be attached to a configuration service version. Edge Dictionaries are made up of dictionary containers and dictionary items. Attaching dictionary containers to a service version allows you to turn frequently repeated statements into single function statements that act as a constant.

    Create an empty dictionary container within a service

    To use a dictionary container, start by creating an empty one within an unlocked version of a service.

    Before an Edge Dictionary can be manipulated, its dictionary container must be associated with at least one service version that is not locked and not active so that the service becomes aware of the dictionary's existence.

    For example, if you were creating a referer blocklist via the API, you would make an API call by running this command:

    1
    
    curl -X POST -H 'Fastly-Key: FASTLY_API_TOKEN' -d 'name=referer_blocklist' https://api.fastly.com/service/<service_id>/version/<version_number>/dictionary
    

    which would return:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    {
      "created_at": "2017-05-03T16:11:41+00:00",
      "deleted_at": null,
      "id": "<dictionary_id>",
      "name": "referer_blocklist",
      "service_id": "<service_id>",
      "updated_at": "2017-05-03T16:11:41+00:00",
      "version": <version_number>,
      "write_only": false
    }
    

    Activate the service associated with the dictionary container

    For an Edge Dictionary to appear in generated VCL so it can be referred to later, the version associated with the dictionary container must be activated.

    In our referer blocklist example, you would make this API call to activate service version associated with the empty dictionary container you created:

    1
    
    curl -X PUT -H 'Fastly-Key: FASTLY_API_TOKEN' https://api.fastly.com/service/<service_id>/version/<version_number>/activate
    

    The response would be this:

    1
    2
    3
    4
    5
    
    {
      "number": <version_number>,
      "active": true,
      "service_id": "<service_id>"
    }
    

    Add dictionary items

    Once the dictionary container becomes associated with the configuration of a service, you can begin populating it with dictionary items. Our guide to working with dictionary items provides more detail on manipulating dictionary items. In the example shown here, you would use the following API call for each URL you want to add to your referer blocklist:

    1
    
    curl -X POST -H 'Fastly-Key: FASTLY_API_TOKEN' -d 'item_key=example-referer.org&item_value=true' "https://api.fastly.com/service/<service_id>/dictionary/<dictionary_id>/item"
    

    The response for each URL added would look similar to this:

    1
    2
    3
    4
    5
    6
    
    {
      "dictionary_id": "<dictionary_id>",
      "service_id": "<service_id>",
      "item_key": "example-referer.org",
      "item_value": "true"
    }
    

    Once the blocklisted URLs are added as items in your dictionary container, you can find them in your generated VCL by looking for a table similar to this:

    1
    2
    3
    4
    5
    
    table referer_blocklist {
      "example-referer.org": "true",
      "another-referer.net": "true",
      "sample-referer.com": "true",
    }
    

    Using a service to call dictionaries

    When you create Edge Dictionaries via API calls, the dictionary contents aren't tied to any single version of your service.

    The logic needed to interact with the table of information the Edge Dictionary creates, however, is always tied to a service version.

    For example, adding a new referer to your blocklist requires that you specifically interact with the Edge Dictionary at some point after you create it. You could do this via API calls because its data would not require a service version activation. The dictionary was created via API calls not via custom VCL.

    Specifically, you would set the host of the referer to a header by including custom VCL like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // versioned vcl
    sub vcl_recv {
    
      # capture host of referer into a header
      set req.http.Referer-Host = regsub(req.http.Referer, "^https?://?([^:/\s]+).*$", "\1");
    
      # check if referrer host is in blocklisted table
      if (table.lookup(referer_blocklist, req.http.Referer-Host)) {
        # ResponseObject: forbidden-referrer
        error 900 "Fastly Internal";
      }
      #end condition
    }
    
    sub vcl_error {
    
      if (obj.status == 900) {
        set obj.http.Content-Type = "";
        synthetic {""};
        return(deliver);
      }
    }
    

    Custom VCL examples

    These examples illustrate how to use Edge Dictionaries in custom VCL. The dictionaries are created via API calls and are displayed in the tables.

    Example: Referer blocklist

    This example returns a 403 error message if the referer is in the dictionary.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    // dictionary items can be added, updated, removed via the API
    // does not require cloning and activating versions
    table bad_actors {
      "example.com" : "nope",
      "fastly.com" : "nope",
    }
    // versioned vcl
    sub vcl_recv {
      set req.http.Referer-Host = regsub(req.http.Referer, "https?://([^/]+)/.*", "\1");
      set req.http.Referer-Check = table.lookup(bad_actors, req.http.Referer-Host, "yes");
      if (req.http.Referer-Check == "nope") {
        error 403;
      }
    }
    

    Example: CORS origin database

    This example adds the origins in the dictionary to the Access-Control-Allow-Origin header.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    // dictionary items can be added, updated, removed via the API
    // does not require cloning and activating versions
    table acceptable_origins {
      "http://example.com" : "yes",
      "http://fastly.com" : "yes",
    }
    // versioned vcl
    sub vcl_deliver {
      set req.http.CORS = table.lookup(acceptable_origins, req.http.Origin, "nope");
      if (req.http.CORS == "yes") {
        set resp.http.Access-Control-Allow-Origin = req.http.Origin;
      }
    }
    

    Example: TTL database

    This example sets the TTLs for the URLs in the dictionary.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    // dictionary items can be added, updated, removed via the API
    // does not require cloning and activating versions
    table ttls {
      "/" : "60",
      "/public" : "86400",
      "/api" : "3600",
      "/foo" : "7200",
      "/user" : "5"
    }
    // versioned vcl
    sub vcl_fetch {
      /* cut URL down to first directory, or just / */
      if (req.url.path ~ "^(/[^/\?]*)") {
        /* should always be true */
        set beresp.ttl = std.atoi(table.lookup(ttls, re.group.1, "30"));
      }
    
    Back to Top