HTTP 405はURLがないerrorと混同せず許可するmethodとformの送信先を確認する
公開日: 執筆:佐藤
HTTP 405 Method Not Allowedは、URLが存在しないことを示すerrorではありません。serverがrequestのmethodを受け付けないときに返す応答です。formをPOSTで送ったのに送信先がGETだけを受ける、APIへPUTを送ったのにそのmethodを許可していない、といったときに起きます。直すべきなのはURLの文字列だけではなく、そのURLで何の操作を受けるかという設計です。
同じ画面をbrowserで開けるのに、formを送ると405になることがあります。これは、browserでpageを開く操作が通常はGET requestであり、form送信がPOST requestになるためです。見ているURLが同じでも、serverへ送るmethodが違えば、serverは別の要求として扱えます。画面が表示されたことだけを、送信先が正しい証拠にしません。
RFC 7231は、405をserverがrequest methodを理解しているが、対象resourceでは許可しない場合のstatus codeと定めています。405 responseには、そのresourceで許可するmethodを示すAllow headerを含める必要があります。error文だけを見るより、request method、response status、Allow header、送信先URLを組にして確認します。
404、403、405は直す場所が違う
formやAPIが期待どおりに動かないとき、すべてを「URL error」として扱うと原因を遠回りします。404はresourceを見つけられない場合、403はserverがrequestを拒否する場合、405はresourceがあってもmethodを許可しない場合です。同じようにerror画面が出ても、確認する設定は違います。
| response | serverが示す状態 | 最初に確認するもの |
|---|---|---|
| 404 Not Found | 対象resourceを見つけられない | URL、path、route、公開場所 |
| 403 Forbidden | resourceへのaccessを許可しない | login、権限、file permission、access rule |
| 405 Method Not Allowed | resourceはあるがmethodを許可しない | GET、POST、PUTなどのmethodとAllow header |
| 500 Internal Server Error | server側で処理できない状態が起きた | error log、application処理、server設定 |
説明用の仮例として、/contact/をbrowserで開くと問い合わせformが表示されるのに、送信buttonを押すと405になる場合を考えます。/contact/がGETで表示できることは、POSTで問い合わせを受けられることを意味しません。formのactionが/contact/を指しているのか、実際には別の/contact/submit/へ送るべきなのかを確認します。送信先が正しくても、serverやapplicationがPOSTを受けるrouteを登録していなければ405になります。
反対に、URLの最後にslashがない、domainが違う、移転先のpathが変わった場合は、404やredirectの問題かもしれません。error codeを確かめずにform pluginを入れ替えたり、URLを手で書き換えたりすると、元の原因を見失います。browserのnetwork記録で、送信時に何が返ったかを見ます。
GETは読む操作、POSTは送る操作として分ける
GETはresourceを取得するためのrequestです。会社案内、商品説明、記事、問い合わせformの入力画面を開くときに使われます。URLへparameterを付けて検索条件を渡す場合も、GETを使うことがあります。GET requestは、利用者が何度も開くことを前提にした情報取得と考えます。
POSTは、formの入力内容を送る、申込みを作る、設定を保存するような処理に使われます。問い合わせ内容を受け取るendpointがPOSTを受け付けないなら、formは正しく送れません。GETで開けるからPOSTも許可すべきだ、と考える必要はありません。表示用のURLと、保存や送信を受けるURLを分ける設計もあります。
| 操作 | methodの例 | 405が出たときに疑うこと |
|---|---|---|
| 記事や会社案内を開く | GET | URL、公開状態、redirect、cache |
| site内検索の条件を送る | GET | parameter名、検索URL、encoding |
| 問い合わせ内容を送る | POST | formのmethod、action、受信側のroute、CSRF対策 |
| 管理画面の設定を保存する | POST | 利用者権限、nonce、保存処理、受信method |
| APIのdataを更新する | PUTまたはPOST | API仕様、認証、許可method、request body |
POSTを受け付けないURLへ、serverの設定で無条件にPOSTを許可すればよいわけではありません。URLが本来は閲覧用なら、入力dataを受け取って保存する処理を増やすことになります。どの利用者が何を送れてよいか、入力を検査するか、重複送信をどう扱うかを決めなければなりません。405を消すことと、送信処理を安全に追加することを同じ作業にしません。
Allow headerはAPI仕様と実装の食い違いを見つける手掛かりになる
405 responseのAllow headerには、対象resourceで許可するmethodが示されます。たとえばAllow: GET, HEADと返るURLへPOSTを送れば、serverは閲覧用としては処理できても、form送信は受けない状態です。Allow headerに期待したPOSTがないなら、formの送信先を間違えたか、applicationまたはserverのroute設定が不足しています。
ただし、Allow headerだけで全てのaccess条件が分かるわけではありません。POSTが許可されていても、loginしていない利用者は403になるかもしれません。POSTを受けるrouteがあっても、CSRF対策のtokenがなければ拒否するかもしれません。request methodが合っていること、利用者が操作してよいこと、送る値が正しいこと、serverが保存できることを順に分けます。
APIの仕様書にPOST /ordersと書かれていても、公開serverが同じpathとmethodを受けているとは限りません。test environmentと本番environmentでdomainやpathが違う場合もあります。APIを外部の制作者へ頼むなら、URLだけでなく、method、必要なheader、認証、許可する利用者、正常時とerror時のresponseを記録します。仕様を作る作業と、実際のserverへ設定する作業を分けます。
formの405は利用者の画面と送信経路を一緒に見る
問い合わせformで405が出るとき、管理画面の設定だけを見て終わりにしません。利用者が入力するpage、formのmethodとaction、browserが実際に送ったrequest、responseのstatus、送信先の処理、通知mailの順をつなげて確認します。formの画面がきれいに見えても、actionが古いURLを指していれば送信は失敗します。
公開前のtestでは、正常な入力で送信し、network画面でrequest URLとmethodを見ます。responseが200やredirectで終わる場合も、完了画面だけを見ず、事業側の通知mailと送信者への案内を確認します。405が返る場合は、error pageへ表示されたmessageだけを記録せず、response headerのAllow、formのHTML、server側のrouteまたはplugin設定を比べます。
formを移転するときは、旧URLから新URLへのredirectも確認します。入力画面を301で移しても、以前のform actionが旧pathへPOSTを送る設計なら、移転先が同じmethodを受けるかを確認する必要があります。閲覧用のGET redirectが動くことと、formのPOSTが動くことは別です。移転後に問い合わせが止まることを防ぐには、実際に送信するtestが必要です。
最初の一手は、405が出るrequestを一つ選び、URL、request method、response status、Allow header、操作の目的を同じメモへ書くことです。serverが何を拒否したかを分けてから、formのactionか、受信側のrouteか、権限設定かを直します。
関連記事

