• HTTP 405はURLがないerrorと混同せず許可するmethodとformの送信先を確認する

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か、権限設定かを直します。

戻る