routing.yml と AllowEncodedSlashes とか

apache環境のsymfonyにて。

routing.yml を使って、

http://hostname/index.php/tag/index?tagname=(何か文字列)

http://hostname/index.php/tag/(何か文字列)

のようなURLでアクセス可能にして、更にmod_rewrite

http://hostname/tag/(何か文字列)

でアクセス可能にする、といったことを最近良くやるのですが、この文字列パラメータに 半角スラッシュが入ってくると面倒なことになります。はまってしまいました。

渡したいパラメータを仮に "news/sports" とします。

半角スラッシュを普通にURLエンコードして渡すと、404エラーに。

スラッシュそのままだとパラメータが途中で区切られてしまうのでURLエンコードは必須だし、
url_for 等のヘルパーでも以下のように勝手にURLエンコードしてくれますが、404エラーになってしまいました。

http://hostname/tag/news%2Fsports

apache側で AllowEncodedSlashes On にして解消されました。

no_script_name: off の環境だと、"%2F" の手前でパラメータが途切れる。

PATH_INFO の中が既にデコードされていました。(なぜそうなるのかは調べてません)

また、パラメータ取得方法が2パターンあるようで

http://hostname/tag/news%2Fsports  ⇒ REQUEST_URIから取得 ⇒ %2FがデコードされてなくてOK
http://hostname/index_dev.php/tag/news%2Fsports ⇒ PATH_INFOから取得 ⇒ %2FがデコードされててNG

といった状況のため、スラッシュを2重エスケープするような対策をすると、今度はprod側のパラメータのほうが、エンコードの解けてない状態でsfRequestにパラメータが入っている状態になってしまいます。

devとprodで挙動が違う、といういやらしい問題にたどり着いてしまいました。

今のところは一旦、コントローラのgenUrlを上書きしたサブクラスを使っていく、アドホックな上書きで回避をしてますが、いい方法がないか調査中です。

(こんなソースを晒すのもどうかとおもいますが、こんな感じです・・・はやく別な方法にしないと。。)

    public function genUrl( $parameters = array(), $absolute = false )
    {
        $url = parent::genUrl( $parameters, $absolute );
        return sfConfig::get('sf_no_script_name') ? $url : str_replace( '%2F', '%252F', $url );
    }