😵

Nuxt3 on Nginx構成でtrailing slash強制リダイレクトを防ぐ方法

に公開

はじめに

Nuxt3 on Nginx構成でフロントエンド開発をしていた際、
/login など末尾にスラッシュを付けずにアクセスしたとき 301 リダイレクト/login/ に書き換わってしまい、検証環境デプロイ時に不具合が発生しました。
この解決に困ったので、書き残したいと思います。

この記事でわかること

  • 末尾スラッシュが強制される Nginx の仕組み
  • 問題の設定箇所の特定方法
  • try_files を使ったリダイレクト回避パターン

症状

$ curl -I http://localhost:3000/login
HTTP/1.1 301 Moved Permanently
Location: http://localhost:3000/login/

/login/ へ 301 で飛ばされる。


原因は index ディレクティブ

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;  # ← これがトリガー
}
  1. /login にリクエストが来る
  2. 実パス /usr/share/nginx/html/login/ がディレクトリとして存在
  3. index.html が見つかる
  4. Nginx は「ディレクトリ=末尾 / 必須」と判断し 301 リダイレクト

リライトルールが無くても、index を指定しているだけで起こる Nginx の標準動作 です。


解決策: try_files に置き換える

もっとも簡単なのは index を外し、try_files で「ファイル or ファイルが無ければそのディレクトリの index.html」を探すようにすることです。

location / {
    root /usr/share/nginx/html;
    try_files $uri $uri/index.html =404;
}
  • $uri … リクエストそのもの (/login)
  • $uri/index.html … ディレクトリ配下の index.html
  • =404 … どちらも無ければ 404 を返す(リダイレクトしない)

手順まとめ

  1. location / ブロックの index 行を削除

  2. 代わりに try_files を追加

  3. 設定をテストしてリロード

    sudo nginx -t       # 構文チェック
    sudo nginx -s reload
    
  4. curl -I http://localhost:3000/login で 301 が消えたことを確認


おわりに

Nginx の「ディレクトリには末尾 /」というお作法は知らないとハマりがちです。
try_files を使えば URL を変えずに静的ファイルをスマートに配信できます。ぜひ試してみてください。


参考リンク

Discussion