nginx の try_files ディレクティブの挙動を見てみた

はじめに

nginx の設定ファイルを書いていてふと try_files ってどんな挙動するんだっけと気になった。この記事では調べた内容、挙動をまとめておく。

結論

シンタックス

ドキュメント を見ると以下のようなシンタックスになっている。

Syntax:	try_files file ... uri;
try_files file ... =code;
Default:	—
Context:	server, location

どういう挙動か

以下に設定ファイルの一例を置いておく。

server {
    ...
    location / {
        ...
+       try_files $uri $uri/ $uri/index.html $uri.html =404;
    }
}
  • try_files ディレクティブに設定してある値を左から順に評価し、サーバ上に静的コンテンツがあれば返す。
  • $uri/ のようにディレクトリも指定可能。
  • 末尾に最終的に見つからなかった場合のステータスコードを定義でき、=code 形式で指定する。
  • (上記には記載はないが)@proxy のように名前付きロケーションにプロキシさせることも可能。

検証

Docker コンテナを使う

検証として公式の nginx:1.23.1 コンテナイメージを使用する。イメージは、Docker Hub から pull できる。

ディレクトリの構成は以下のようにいくつかの静的コンテンツを用意しておく。ここで使用する HTML ファイルの中身はそれぞれの区別ができれば何でも良い)

tree .
.
├── contents
│   ├── hoge
│   │   └── index.html
│   └── index.html
└── nginx.conf

2 directories, 3 files

nginx の設定ファイルは以下。

nginx.conf
server {
    listen       80;
    root         /usr/share/nginx/html;

    include /etc/nginx/default.d/*.conf;

    location / {
        index     index.html index.htm index.php;
        try_files $uri $uri/ $uri/index.html $uri.html =404;
    }
}

nginx コンテナをデバッグモードで起動する。

起動時に -v(--volume) オプションを用いて設定ファイルとコンテンツをマウントする。また、-p(--publish) オプションを用いてコンテナ上の 80 番ポートとホスト上の 8080 番ポートをバインドする。

$ docker run -itd --rm --name nginx \
    -v ${PWD}/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
    -v ${PWD}/contents/:/usr/share/nginx/html:ro  \
    -p 8080:80 \
    nginx:1.23.1 nginx-debug -g 'daemon off;'

cURL でアクセス

/ ルートにアクセスすると、./contents/index.html の内容が返る。

$ curl http://localhost:8080
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to nginx!</title>
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
  </body>
</html>

/hoge にアクセスすると、./contents/hoge/index.html の内容が返る。

$ curl http://localhost:8080/hoge
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to hoge page!</title>
  </head>
  <body>
    <h1>Welcome to hoge page!</h1>
  </body>
</html>

/hoge/ にアクセスすると、./contents/hoge/index.html の内容が返る。

$ curl http://localhost:8080/hoge/
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to hoge page!</title>
  </head>
  <body>
    <h1>Welcome to hoge page!</h1>
  </body>
</html>

/hoge/index.html にアクセスすると、./contents/hoge/index.html の内容が返る。

$ curl http://localhost:8080/hoge/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to hoge page!</title>
  </head>
  <body>
    <h1>Welcome to hoge page!</h1>
  </body>
</html>

存在しないパス /aaaaaaaaaaaaaa にアクセスすると、ステータスコード 404 とデフォルト 404 ページの内容が返る。

$ curl http://localhost:8080/aaaaaaaaaaaaaa
<html>
  <head><title>404 Not Found</title></head>
  <body>
    <center><h1>404 Not Found</h1></center>
    <hr><center>nginx/1.23.1</center>
  </body>
</html>

まとめ

結論としては try_files は左から順に評価されるので、書く順番が重要。必要に応じて末尾にステータスコードを定義したり、名前付きロケーションを使って動的なパスへのプロキシ設定などをしてあげると良さそう。ちゃんと理解できたので使いこなしていきたい。

参考

Module ngx_http_core_module
Module ngx_http_core_module favicon nginx.org
Nginxのtry_filesディレクティブ設定例 - Qiita
Nginxの設定にて、静的なファイルと動的なURLを振り分けたいことがあります。try_filesを利用すれば、指定した順番で確認と転送を実施してくれます。参考Module ngx_http_c…
Nginxのtry_filesディレクティブ設定例 - Qiita favicon qiita.com
Nginxのtry_filesディレクティブ設定例 - Qiita