route
ディレクティブのグループを文字通り、単一のユニットとして評価します。
routeブロックに含まれるディレクティブは、内部的に並べ替えられません。 HTTPハンドラディレクティブ(ハンドラまたはミドルウェアをチェーンに追加するディレクティブ)のみがrouteブロックで使用できます。
このディレクティブは、そのサブディレクティブも通常のディレクティブであるという点で特殊なケースです。
構文
route [<matcher>] {
<directives...>
}
- <directives...> は、routeブロックの外側と同じように、1行に1つずつディレクティブまたはディレクティブブロックのリストです。ただし、これらのディレクティブは並べ替えられません。 HTTPハンドラディレクティブのみを使用できます。
ユーティリティ
routeディレクティブは、特定の高度なユースケースやエッジケースで、HTTPハンドラチェーンの一部を絶対的に制御するために役立ちます。
HTTPミドルウェアの評価の順序は重要であるため、Caddyfileは通常、解析後にディレクティブを並べ替えて、Caddyfileを使いやすくします。入力する順序を気にする必要はありません。
組み込みの順序はほとんどのサイトと互換性がありますが、場合によっては、サイト全体またはその一部に対して手動で順序を制御する必要がある場合があります。それがrouteディレクティブの目的です。
例として、redirとfile_serverという2つの終端ハンドラーを考えてみましょう。どちらもクライアントに応答を書き込み、チェーン内の次のハンドラーを呼び出さないため、特定の要求に対してはどちらか1つのみが実行されます。では、どちらが先に来るのでしょうか?通常、redirは、特定のケースでのみリダイレクトを発行し、一般的なケースではファイルを提供する必要があるため、file_serverよりも前に実行されます。
ただし、2番目のディレクティブ(redir)が2番目(file_server)よりも具体的なマッチャーを持っている場合があります。言い換えれば、一般的なケースでリダイレクトし、特定のファイルのみを提供したいということです。
したがって、次のようなCaddyfileを試すかもしれません(しかし、これは期待どおりに動作しません!)
example.com {
file_server /specific.html
redir https://anothersite.com{uri}
}
問題は、ディレクティブがソートされた後、redirがfile_serverの前に来るということです。
しかし、この場合、redirのマッチャー(暗黙的な*)は、file_serverのマッチャー(*は/specific.htmlのスーパーセット)のスーパーセットです。
幸いなことに、解決策は簡単です。これらの2つのディレクティブをrouteブロックでラップして、file_serverがredirの前に実行されるようにします。
example.com {
route {
file_server /specific.html
redir https://anothersite.com{uri}
}
}
これで、順序が文字通りに解釈されるため、file_serverはredirの前にチェーンされるようになります。
類似のディレクティブ
HTTPハンドラディレクティブをラップできる他のディレクティブもありますが、それぞれが伝えたい動作に応じて使用されます。
-
handleは、routeのように他のディレクティブをラップしますが、2つの違いがあります。1)handleブロックは互いに排他的であり、2)handle内のディレクティブは通常並べ替えられます。 -
handle_pathはhandleと同じですが、ハンドラーを実行する前にリクエストからプレフィックスを削除します。 -
handle_errorsはhandleに似ていますが、Caddyがリクエスト処理中にエラーが発生した場合にのみ呼び出されます。
例
/apiへのリクエストはそのままプロキシし、それ以外のすべてのリクエストは、ディスク上のファイルと一致するかどうかに基づいて書き換え、それ以外の場合は/index.htmlを書き換えます。次に、そのファイルが提供されます。
try_filesはreverse_proxyよりもディレクティブの順序が高いため、通常はソートされて最初に実行されます。これにより、APIリクエストがすべて/index.htmlに書き換えられ、/api*と一致しなくなるため、プロキシされなくなり、代わりにfile_serverから404になります。すべてをrouteでラップすると、リクエストが書き換えられる前に、常にreverse_proxyが最初に実行されるようになります。
example.com {
root * /srv
route {
reverse_proxy /api* localhost:9000
try_files {path} /index.html
file_server
}
}