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

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

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