何が起きたか
jsでajax通信がしたく以下のように書いた。
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json; charset=utf-8" },
body: JSON.stringify(parameters)
})
これで、バリデーションエラーで弾かれた場合、Laravelからはステータスコード422とエラーメッセージが帰ってくるはずだった。
なのに、ステータスコードは405でしかもエラーメッセージは何も帰ってこない。
これの解決に3時間くらいかかってしまったのでここに残しておく。
結論
headersには"X-Requested-With": "XMLHttpRequest"
が必要。
解説
結論を見れば分かるかもしれないが、Laravel(正確には拡張元のsymfony)はリクエストヘッダーの上記を見てajaxかどうかを判断している。
なのでこれを入れないと、Laravelは通常のリクエストと判断しフォーム画面に戻すべくRedirectResponseを返す。
これにより、何等かの原因で405というおかしなコードが帰ってきた(この時点でおかしいことは分かったのでこれ以上は詳しくは見ていない)。
実際にソースを追ってみたところ以下のようになっている。
- まずここで、バリデーションに引っ掛かった場合は
failedValidation()
を実行しValidationExceptionをthrow - 例外ハンドラがValidationExceptionをcatchし、ここでJsonResponseを返すかRedirectResponseを返すかを分岐
-
expectsJson()
はここでajax()
の結果からajax通信かどうかを見ており -
ajax()
はここでxmlHttpRequestかを見ており - xmlHttpRequestかはここで
"X-Requested-With": "XMLHttpRequest"
かを見ている
所感
「laravel fetch 405」とかでググってもヒットしないものだから苦労した。。常識なのだろうか。
常識なのであればこの機会に知ってよかったと思うことにする。