冒頭まとめ

Nginx で 405 Not Allowed が返ったら、要求の方法を表すメソッドと、送信先の URL を確認してください。フォームや API の POST が、アプリではなく静的ファイルの処理へ渡っている可能性があります。

Nginx の静的ファイルの処理は、存在する通常のファイルへの POST を 405 で拒否します。POST を禁止する設定を書いていなくても起きます。送信内容を保存・処理したい場合は、その処理を担当するアプリへ要求が届くように直します。

エラーの概要

Nginx の既定のエラーページには、次の見出しが使われます。

405 Not Allowed

これは既定ページの実装にある文言です。ただし、画面に Nginx の名前が出ていても、Nginx の静的ファイル処理が拒否したとは限りません。転送先のアプリが返したエラーや、独自のエラーページが関わる構成もあります。

例えば、/contact.html を表示する GET が成功しても、同じ URL にフォームを POST できるとは限りません。HTML ファイルを返す処理と、フォームの内容を受け取る処理は別です。

まず最初に:送信先とメソッドを確認する

フォームなら action と method、JavaScript からの要求なら URL と method の指定を確認します。送信先に .html や .json が付いているかだけで判断せず、その URL をどの処理へ渡す設定になっているかを調べてください。

管理者は、稼働中の Nginx の設定を確認します。

sudo nginx -T

公式資料によると、-T は設定の検査に加えて設定ファイルを出力します。秘密情報や内部の接続先が含まれる場合があるため、出力をそのまま外部へ共有しないでください。

対象の server と location をたどり、静的ファイルを返す設定か、proxy_pass や fastcgi_pass でアプリへ渡す設定かを確認します。要求の処理方法の公式説明では、接続先やホスト名、URL に基づいて処理する設定が選ばれることが説明されています。

よくある原因と解決手順

静的ファイルへ POST している

静的ファイル処理の実装では、POST の場合、ファイルを開く処理の後に 405 を返す経路があります。通常のファイルが存在し、開ける場合でも、POST の内容を処理するわけではありません。

フォームの送信先が表示用の HTML ファイルになっているなら、アプリの受付 URL へ変更します。例えばアプリが /api/contact で POST を受ける設計なら、フォームや JavaScript の送信先もその URL に合わせます。

単にファイルを読みたいだけなら GET が適切ですが、登録や更新の要求を、405 を避けるためだけに GET へ変更しないでください。何を行う要求かに合わせて、受付側の処理を用意します。

アプリへ渡すはずの URL が静的ファイル処理へ回っている

Nginx の設定例として、アプリが同じ機器の 127.0.0.1:3000 で /api/contact を受け付けるなら、次のように /api/ への要求を転送できます。既存の server の中に置く部分的な例です。

location ^~ /api/ {
    proxy_pass http://127.0.0.1:3000;
}

接続先とポート番号は例です。Docker など別の構成では、Nginx から接続できる実際のアプリのアドレスに置き換えてください。

proxy_pass の公式資料によると、転送先に URI を付けない場合、元の要求 URI が転送されます。この例では /api/contact をアプリ側でも受け付ける必要があります。末尾に / を追加すると URI の扱いが変わるため、アプリが待ち受けるパスに合わせて設定します。

PHP の場合は、PHP を実行する設定へ要求が渡る必要があります。既存のアプリの構成を確認し、HTML や JSON を配置しただけで送信処理ができるとは考えないでください。

PUT・DELETE・OPTIONS などが静的ファイル処理へ届いている

同じ実装では、GET・HEAD・POST 以外のメソッドを、ファイルの確認より前に 405 にする経路があります。そのため、POST と違って、ファイルの有無を確認する前に拒否される場合があります。

API 用の PUT や DELETE、ブラウザーが送る OPTIONS で失敗した場合も、まずその要求を扱うアプリや処理へ渡っているか確認します。limit_except に POST などを書き足しても、静的ファイルを処理する機能がアプリの代わりになるわけではありません。

WebDAV でファイル管理を行いたい

Nginx 自身にファイルの作成や削除を担当させる目的なら、WebDAV の機能が別にあります。公式資料では、PUT・DELETE・MKCOL・COPY・MOVE を扱うモジュールと dav_methods が説明されています。標準のビルドでは有効にならないモジュールです。

通常のフォームや API の 405 の対処として有効にするものではありません。ファイルを変更できる機能なので、用途とアクセス制限を決めたうえで構成します。

補足:似ているが別のもの

404 は対象が見つからない場合の状態コードです。静的ファイルへの POST では、ファイルが存在しない場合に、POST を拒否する判定より先に 404 になる経路があります。ただし、別の処理や内部転送がある構成まで、この結果を一般化することはできません。

403 はアクセスが拒否された場合に確認する状態コードです。limit_except は指定したメソッド以外に対するアクセス制限を設定する仕組みで、ファイルへの書き込みやフォーム処理を実装するものではありません。

切り分けの順序

最初に、失敗した要求の URL とメソッドを確認します。次に、その URL が Nginx のどの location に入り、静的ファイル処理とアプリへの転送のどちらへ進むかを調べます。

アプリへ渡す設計なら、転送先の接続先とパス、アプリが受け付けるメソッドを確認してください。アプリ側のアクセスログも同じ時刻で照合します。

error_page で 405 を 200 に変えることを、フォーム処理の修正の代わりにはできません。公式資料によると、通常の別 URI へのエラー処理では GET・HEAD 以外が GET に変わります。ファイルを表示できても、送信内容を保存したことにはなりません。

確認コマンド集

次は、管理している検証環境の同じ静的ファイルに、GET と POST を送って比較する例です。実在するファイルの URL に置き換えてください。本番の受付処理へ、確認目的の POST を無計画に送らないでください。

# GET の応答を確認する
curl -i https://example.com/index.html

# 空の POST を送り、応答を比較する
curl -i --data '' https://example.com/index.html

# 設定全体を確認する
sudo nginx -T

# 設定変更後に検査する
sudo nginx -t

curl の --data は、公式マニュアルで説明されている POST の送信指定です。設定の検査に成功したら、対象環境の管理方法に従って Nginx の設定を再読み込みし、元の操作を確認してください。

Editor’s Note

405 が出たときは、メソッドを許可する設定を探す前に、要求を受け取った処理を確認することが大切です。静的ファイルを返す処理へフォームの送信が届いているなら、必要なのは送信先と受付処理をそろえることです。

本記事の静的ファイルの判定順序は、確認時点の Nginx の公開実装に基づきます。URL が / で終わる場合や、内部転送、認証、別のモジュールが関わる構成では、同じ結果になるとは限りません。画面の文言だけで判断せず、対象の設定と処理経路を確認してください。


免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。