symfonyでETag設定を有効にした場合に304応答が返されるように修正
先日調査したsymfonyのキャッシュの挙動まとめ - しんふぉにゃんのエントリに書いた修正点ですが、symfomnyのコードを直接書き換えるのではなく、以下のようにして適用しました。
1. sfCacheFilterの派生クラスを作成して、lib配下に保存(ここれはxnniCacheFilter.class.phpとしています)
<?php // lib/xnniCacheFilter.class.php // class xnniCacheFilter extends sfCacheFilter { // // executeBeforeExecutionをオーバーライド(挙動がおかしいのを修正) // public function executeBeforeExecution() { $uri = $this->routing->getCurrentInternalUri(); if (is_null($uri)) { return true; } // page cache $cacheable = $this->cacheManager->isCacheable($uri); if ($cacheable && $this->cacheManager->withLayout($uri)) { $inCache = $this->cacheManager->getPageCache($uri); $this->response = $this->context->getResponse(); // <GOTO> キャッシュから読み込んだ場合はresponseオブジェクトの参照を再設定する $this->cache[$uri] = $inCache; if ($inCache) { // page is in cache, so no need to run execution filter return false; } } return true; } // // checkCacheValidationのオーバーライド(挙動がおかしいのを修正) // protected function checkCacheValidation() { // Etag support if (sfConfig :: get('sf_etag')) { $etag = '"' . md5($this->response->getContent()) . '"'; if ($this->request->getHttpHeader('IF_NONE_MATCH') == $etag) { $this->response->setStatusCode(304); $this->response->setHeaderOnly(true); if (sfConfig :: get('sf_logging_enabled')) { $this->context->getEventDispatcher()->notify(new sfEvent($this, 'application.log', array ( 'ETag matches If-None-Match (send 304)' ))); } } } // conditional GET support // never in debug mode if ($this->response->hasHttpHeader('Last-Modified') && !sfConfig :: get('sf_debug')) { $lastModified = $this->response->getHttpHeader('Last-Modified'); if ( is_array($lastModified) ) { // <GOTO> 戻り値が配列なら処理する $lastModified = $lastModified[0]; } if ($this->request->getHttpHeader('IF_MODIFIED_SINCE') == $lastModified) { $this->response->setStatusCode(304); $this->response->setHeaderOnly(true); if (sfConfig :: get('sf_logging_enabled')) { $this->context->getEventDispatcher()->notify(new sfEvent($this, 'application.log', array ( 'Last-Modified matches If-Modified-Since (send 304)' ))); } } } } }
2. このフィルタを使用するようにfilters.yml(app/frontend/config/filters.yml)を修正
cache: class: xnniCacheFilter
これでキャッシュをクリアすると、sfCacheFilterの代わりにxnniCacheFilterが使われるようになり、オーバーロードしたメソッドが呼び出されるようになります。
で、ETagが一致する場合は304 Not Modifiedが正しく返されるようになります。