強引にaction名がマルチバイトなURLにアクセス⇒500エラー

routing.ymlはデフォルトのままで、

http://hostname/mymodule/%E3%81%BB%E3%81%92%E3%81%BB%E3%81%92

とかに無理やりアクセスすると変なエラーがでます。

No suitable nodes are available to serve your request.(500エラー)

とか

Fatal error: Maximum function nesting level of '100' reached, aborting!
in /usr/share/php/symfony/debug/sfWebDebug.class.php on line 89

とか・・・


調べてみると、action名がマルチバイトという異常系のときに、action_name が空にされた状態のままaction実行まで流れてきてて、sfActions->execute() が再帰的に実行されている現象が確認できました。

500エラーでもいいような気がするのですが、該当するactionが無いということでの404にしたかったので、filterをつくって404を出力するようにしました。

<?php
/**
 * action名が変な場合404にするfilter
 *
 * @package    yoshihi6
 * @subpackage contents-lib
 * @author     yoshihi6
 * @version    SVN: $Id: $
 */
    
class validateActionNameFilter extends sfFilter
{
    public function execute( $filter_chain )
    {
        // get the context
        $context    = $this->getContext();

        // get the current action information
        $moduleName = $context->getModuleName();
        $actionName = $context->getActionName();
        
        if( $actionName === '' ){
            throw new sfError404Exception();
        }else{
            $filter_chain->execute();
        }
    }
}

クラス命名があまりよろしくないかも・・・考えておきます。

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 );
    }

ちょっとだけつかってみた

http://d.hatena.ne.jp/yoshihi6/20080521

  • 総じて軽快だった
  • hg serveは、お手軽でよい
  • hgwebdir.cgiも、お手軽でよい
  • TortoiseHGでは、push/pullは Synchronyzeウインドウを立ち上げてからやる必要があるのが仰々しい。慣れたら面倒にならないだろうか。
  • リポジトリの場所が、最初だけ感覚的にわかりづらかった
  • コミットメッセージが空だとcommitできなかった
  • update、commit、push、pull時に、どのファイルが対象のなってるのかがわかりづらかった

慣れの問題がだいぶある気がします。実はあんまり触ってないので、問題点は何か回避方法があるような気がしなくもないですし。

Mercurial

分散リポジトリ形式のバージョン管理ツール
http://www.selenic.com/mercurial/

svnより高速らしいので、そろそろ試してみようと思います。

個人的な感覚では、分散リポジトリは少々複雑すぎる気がします。チームで使う際の効果を考えると、プロジェクトでは技術者以外も絡めて使っていきたかったりするのですが、svnですら、導入が大変だったりしました。svkなんかは薦めようがなかったりします。

こういった点が実際どうなのか使ってみて確かめます。


Mercurialだとtracが使えなくなるな・・・と思いきや、対応させるプラグインがあるみたいなので、svnからの移行はしやすそうです。

TortoiseHG ていうのがあるのもいいですね。TortoiseCVS/SVNは導入を進める上では神なソフトだったので期待。

Mercurial Plugin for Trac
http://trac.edgewall.org/wiki/TracMercurial

TortoiseHG
http://tortoisehg.sourceforge.net/