public
Description: Radiant is a no-fluff, open source content management system designed for small teams.
Homepage: http://radiantcms.org/
Clone URL: git://github.com/radiant/radiant.git
radiant / lib / radiant / cache.rb
100644 84 lines (72 sloc) 2.609 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
require 'rack/cache'
# So we can subclass the storage types
require 'rack/cache/storage'
require 'rack/cache/metastore'
require 'rack/cache/entitystore'
 
module Radiant
  module Cache
    mattr_accessor :meta_stores, :entity_stores, :use_x_sendfile, :use_x_accel_redirect
    self.meta_stores ||= []
    self.entity_stores ||= []
    self.use_x_sendfile = false
    self.use_x_accel_redirect = nil
 
    def self.new(app, options={})
      self.use_x_sendfile = options.delete(:use_x_sendfile) if options[:use_x_sendfile]
      self.use_x_accel_redirect = options.delete(:use_x_accel_redirect) if options[:use_x_accel_redirect]
      Rack::Cache.new(app, {
          :entitystore => "radiant:cache/entity",
          :metastore => "radiant:cache/meta",
          :verbose => false}.merge(options))
    end
 
    def self.clear
      meta_stores.each {|ms| ms.clear }
      entity_stores.each {|es| es.clear }
    end
 
    class EntityStore < Rack::Cache::EntityStore::Disk
      def initialize(root="#{Rails.root}/cache/entity")
        super
        Radiant::Cache.entity_stores << self
      end
 
      def clear
        Dir[File.join(self.root, "*")].each {|file| FileUtils.rm_rf(file) }
      end
    end
 
    class MetaStore < Rack::Cache::MetaStore::Disk
      def initialize(root="#{Rails.root}/cache/meta")
        super
        Radiant::Cache.meta_stores << self
      end
 
      def clear
        Dir[File.join(self.root, "*")].each {|file| FileUtils.rm_rf(file) }
      end
 
      private
      def restore_response(hash, body)
        # Cribbed from the Rack::Cache source
        status = hash.delete('X-Status').to_i
        response = Rack::Cache::Response.new(status, hash, body)
 
        # Add acceleration headers
        if Radiant::Cache.use_x_sendfile
          accelerate(response, 'X-Sendfile', File.expand_path(body.path))
        elsif Radiant::Cache.use_x_accel_redirect
          virtual_path = File.expand_path(body.path)
          entity_path = File.expand_path(Radiant::Cache.entity_stores.first.root)
          virtual_path[entity_path] = Radiant::Cache.use_x_accel_redirect
          accelerate(response,'X-Accel-Redirect', virtual_path)
        end
        response
      end
      
      def accelerate(response, header, value)
        response.headers[header] = value
        response.body = []
        response.headers['Content-Length'] = '0'
      end
    end
  end
end
 
# Add our classes as fake constants in the right place
class Rack::Cache::EntityStore
  RADIANT = Radiant::Cache::EntityStore
end
 
class Rack::Cache::MetaStore
  RADIANT = Radiant::Cache::MetaStore
end