API による Edge Dictionary の使用

Edge Dictionary を使用して、設定サービスのバージョンに付加する必要のないロジックを作成することができます。Edge Dictionary は、ディクショナリコンテナとディクショナリ項目で構成されています。ディクショナリコンテナをサービスバージョンに付加することで、頻繁に繰り返されるステートメントを、定数として機能する単一の関数ステートメントに変えることができます。

サービス内に空のディクショナリコンテナを作成する

ディクショナリコンテナを使用するには、まず、ロックされていないバージョンのサービス内に空のディクショナリコンテナを作成します。

Edge Dictionary を使用するためには、そのディクショナリコンテナが、ロックも有効化もされていないサービスバージョンの少なくとも1つと関連付けられ、そのサービスがディクショナリの存在を認識できるようにする必要があります。

例えば、API を使ってリファラーブロックリストを作成する場合は、以下のコマンドを実行して API コールを行います。

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

これにより以下が返されます。

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
}

ディクショナリコンテナに関連付けられたサービスを起動する

生成された VCL に Edge Dictionary を表示して後で参照できるようにするには、ディクショナリコンテナに関連付けられたバージョンを有効にする必要があります。

リファラーブロックリストの例では、作成した空のディクショナリコンテナに関連付けられたサービスバージョンを有効にするために、以下の API コールを行います。

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

レスポンスは以下のようになります。

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

ディクショナリ項目の追加

ディクショナリコンテナがサービスの設定と関連付けられたら、ディクショナリ項目の追加を開始できます。ディクショナリ項目の使用に関するガイドに、ディクショナリ項目の設定に関する詳細が記載されています。ここでの例では、リファラーブロックリストに追加したい各 URL に対して、以下の API コールを使用します。

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"

追加された各 URL に対するレスポンスは以下のようになります。

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

ブロックリストに登録された URL がディクショナリコンテナの項目として追加されると、以下のようなテーブルを探すことで、生成された VCL でそれらを見つけることができます。

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

サービスを使用してディクショナリを呼び出す

API コールで Edge Dictionary を作成した場合、ディクショナリのコンテンツは、サービスのどのバージョンにも紐づけられていません。

しかし、Edge Dictionary が作成する情報のテーブルに_アクセス_するのに必要なロジックは、常にサービスのバージョンに関連付けられています。

例えば、新しいリファラーをブロックリストに追加するには、ブロックリストを作成した後に Edge Dictionary とやり取りをする必要があります。そのデータはサービスバージョンの有効化を必要としないため、API コールでこれを行うことができます。ディクショナリがカスタム VCL ではなく、API コールで作成されます。

具体的には、以下のようなカスタム VCL を使用して、リファラーの Host をヘッダーに設定します。

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);
  }
}

カスタム VCL の例

以下の例は、カスタム VCL で Edge Dictionary を使用する方法を示しています。ディクショナリは API コールで作成され、テーブルに表示されます。

例:リファラーブロックリスト

この例では、リファラーがディクショナリにある場合、403エラーメッセージを返します。

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;
  }
}

例:CORS オリジンデータベース

この例では、ディクショナリで設定されているオリジンが Access-Control-Allow-Origin ヘッダーに追加されます。

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;
  }
}

例:TTL データベース

この例では、ディクショナリに登録されている URL の TTL が設定されます。

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