RailsのETag

Tsukasa OISHI

 kaeruspoonのフロントエンドのパフォーマンスチューニングの続き。
 AmazonやYoutubeやニコニコ動画などの画像をキャッシュするようにしてDNSlookupを減らしたのと、Expiresも付与してあげたらYSlowの測定結果がB(80)になりました。最初はFランクだったのに。
 そういえばRailsがなにやら勝手にETagをつけてたみたいなので探ってみたら、actionpack-2.1.0/lib/action_controller/response.rbで以下のような処理をしていた。

    private
      def handle_conditional_get!
        if body.is_a?(String) && (headers['Status'] ? headers['Status'][0..2] == '200' : true)  && !body.empty?
          self.headers['ETag'] ||= %("#{Digest::MD5.hexdigest(body)}")
          self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']

          if request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
            self.headers['Status'] = '304 Not Modified'
            self.body = ''
          end
        end
      end

どうもレスポンスのbodyの内容のMD5値をETagにしているみたい。kaeruspoonでは独自のAmazon広告が毎回違う内容で入るので、あまり意味がないです。ETagは全然使わない方針なので、config/initializers/response.rbを作ってオーバライドしておきました。

module ActionController
  class AbstractResponse #:nodoc:
    private

    def handle_conditional_get!
      if body.is_a?(String) && (headers['Status'] ? headers['Status'][0..2] == '200' : true)  && !body.empty?
        self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
      end
    end
  end
end