Fastly の request condition は最後にマッチした condition が適用される

Fastly で条件に応じて origin(backend) を切り替えたいときは request condition を設定することで実現できます。Request condition の挙動を勘違いしてハマったので、何を勘違いしてどう対応したのか紹介します。

Request condition

Request condition には priority があり、default は 10 で、値が低いほど最初に評価されます。このとき、priority に関係なく、最終的にはすべての request condition が評価されます。以下のような request condition があるとします。

  • Request condition 1
    • priority: 10
    • condition: req.http.host == "foo.example.com" && req.url.path ~ "^/v2"
    • backend: bar.example.com
  • Request condition 2
    • priority: 20
    • condition: req.http.host == "foo.example.com"
    • backend: foo.example.com

この設定にすると foo.example.com/v2/ping というリクエストのときは backend を bar.example.comfoo.example.com/v1/ping へのリクエストは backend を foo.example.com にできると思っていたのですが、foo.example.com/v2/ping の backend は foo.example.com になっていました。これは、request condition は priority が低い順に評価されますが、条件にマッチしたら評価されなくなるわけではないためです。VCL としては以下のようになります。

# Request Condition: api_v2 Prio: 10 if( req.http.host == "foo.example.com" && req.url.path ~ "^/v2/" ) { set req.backend = F_bar_example_com; } #end condition # Request Condition: api_v1 Prio: 20 if( req.http.host == "foo.example.com") { set req.backend = F_foo_example_com; } #end condition
Code language: PHP (php)

このように if 文が request condition の数だけ生成されるので、priority の値が大きい condition にもマッチすれば backend はそれになります。
そのため、request condition を設定する際は、以下のいずれかの対応が必要です。

  • 複数の request condition にマッチしないような条件を設定する
  • priority を適切に設定し、複数の request condition にマッチしても意図した挙動になるようにする

Leave a Reply