はじめに
ある機能を開発中、URLのパス部分で値を受け取ろうとした際に、意図した通りに動作せず404エラーが発生しました。調査の結果、スラッシュ(/)が予約文字であり、パス中で安全に利用できないことが原因でした。
その対応として、クエリパラメータを使う実装に切り替えたので、備忘録としてまとめておきます。
発生した問題
次のようなURLで、hoge/fuga を1つのパラメータとして渡したいと考えていました。
perl
コードをコピーする
https://example.com/path/hoge%2Ffuga/
Laravelのルーティング設定は以下のようにしていました。
php
コードをコピーする
Route::get('/path/{param}', 'HogeController@index');
しかし、上記のURLでは hoge%2Ffuga をパラメータとして受け取ることができず、404エラーが発生してしまいました。
原因の調査
RFC 2396(URLに関する公式仕様)によると、スラッシュ(/)は「予約文字」とされており、URLのパス部分において特別な意味を持つため、エンコードされたとしてもパスの一部としては扱えません。
参考リンク:
RFC 2396 – Uniform Resource Identifiers (URI): Generic Syntax
解決方法:クエリパラメータに変更
パスではなく、クエリパラメータで値を渡すように実装を変更しました。
修正後のルーティング
php
コードをコピーする
Route::get('/path', 'HogeController@index');
値の取得方法
php
コードをコピーする
$url = $request->query('url');
アクセス例
bash
コードをコピーする
https://example.com/path?url=hoge/fuga
この形式であれば、hoge/fuga を1つの文字列として安全に受け取ることができます。
まとめ
URLのパスに含める文字には注意が必要です。特に以下の文字は「予約文字」に該当し、URLパスでは意図通りに使えない場合があります。
ini
コードをコピーする
; / ? : @ & = + $ ,
今回のようにパラメータにスラッシュを含めたい場合は、クエリパラメータを使うのが安全です。
地味な落とし穴ですが、調査に時間を使ったので、今後のために記録しておきます。
ご覧いただき、ありがとうございました。