serve 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +11 -0
- data/Gemfile +17 -14
- data/Gemfile.lock +53 -26
- data/LICENSE +1 -1
- data/QUICKSTART.rdoc +137 -27
- data/README.rdoc +115 -23
- data/VERSION +1 -1
- data/bin/serve +3 -3
- data/lib/serve.rb +2 -5
- data/lib/serve/application.rb +7 -6
- data/lib/serve/handlers/dynamic_handler.rb +40 -42
- data/lib/serve/handlers/less_handler.rb +19 -0
- data/lib/serve/handlers/sass_handler.rb +5 -0
- data/lib/serve/out.rb +19 -1
- data/lib/serve/project.rb +2 -2
- data/lib/serve/rack.rb +58 -18
- data/lib/serve/router.rb +43 -0
- data/lib/serve/templates/config.ru +14 -10
- data/lib/serve/view_helpers.rb +36 -24
- data/spec/fixtures/directory/index.html +1 -0
- data/spec/fixtures/hello.html +1 -0
- data/spec/fixtures/stylesheets/application.sass +3 -0
- data/spec/router_spec.rb +60 -0
- data/spec/spec_helper.rb +0 -1
- metadata +50 -39
- data/lib/serve/file_resolver.rb +0 -48
- data/lib/serve/handlers/markdown_handler.rb +0 -10
- data/lib/serve/handlers/static_handler.rb +0 -22
- data/lib/serve/handlers/textile_handler.rb +0 -10
- data/lib/serve/rails.rb +0 -4
- data/lib/serve/rails/configuration.rb +0 -69
- data/lib/serve/rails/mount.rb +0 -38
- data/lib/serve/rails/routing.rb +0 -25
- data/lib/serve/rails/serve_controller.rb +0 -52
- data/lib/serve/response_cache.rb +0 -170
- data/spec/response_cache_spec.rb +0 -248
@@ -1,22 +0,0 @@
|
|
1
|
-
module Serve #:nodoc:
|
2
|
-
class StaticHandler < FileTypeHandler #:nodoc:
|
3
|
-
extension 'txt', 'text', 'xml', 'atom', 'rss', 'rdf', 'htm', 'html'
|
4
|
-
|
5
|
-
def content_type
|
6
|
-
case File.extname(@script_filename)
|
7
|
-
when '.txt', '.text'
|
8
|
-
'text/plain'
|
9
|
-
when '.xml'
|
10
|
-
'text/xml'
|
11
|
-
when '.atom'
|
12
|
-
'application/atom+xml'
|
13
|
-
when '.rss'
|
14
|
-
'application/rss+xml'
|
15
|
-
when '.rdf'
|
16
|
-
'application/rdf+xml'
|
17
|
-
else
|
18
|
-
'text/html'
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/serve/rails.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
module Serve # :nodoc:
|
2
|
-
module Rails
|
3
|
-
class Configuration # :nodoc:
|
4
|
-
attr_reader :mounts, :view_helpers
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
Serve::ResponseCache.defaults.update(
|
8
|
-
:logger => ActionController::Base.logger,
|
9
|
-
:perform_caching => ActionController::Base.perform_caching
|
10
|
-
)
|
11
|
-
|
12
|
-
@mounts = []
|
13
|
-
|
14
|
-
define_find_cache do |request|
|
15
|
-
@default_cache ||= Serve::ResponseCache.new(
|
16
|
-
:directory => File.join(::Rails.root, 'tmp', 'serve_cache')
|
17
|
-
)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def define_find_cache(&block)
|
22
|
-
singleton_class.module_eval do
|
23
|
-
define_method :find_cache, &block
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def mount(route, root_path)
|
28
|
-
m = Mount.new(route, root_path)
|
29
|
-
@mounts << m
|
30
|
-
yield m if block_given?
|
31
|
-
m
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Answer the cache for the given request. Delegates to the 'find_cache'
|
36
|
-
# block, which defaults to a single cache.
|
37
|
-
#
|
38
|
-
def self.cache(request)
|
39
|
-
configuration.find_cache(request)
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.configuration
|
43
|
-
@configuration ||= Configuration.new
|
44
|
-
end
|
45
|
-
|
46
|
-
# The most powerful way to configure Serve::Rails, the configuration is
|
47
|
-
# yielded to the provided block. Multiple calls are cumulative - there is
|
48
|
-
# only one configuration instance.
|
49
|
-
#
|
50
|
-
def self.configure
|
51
|
-
yield configuration
|
52
|
-
end
|
53
|
-
|
54
|
-
# Define the strategy for resolving the cache for a request. This allows
|
55
|
-
# applications to provide logic like cache-per-browser. The default is a
|
56
|
-
# single cache.
|
57
|
-
#
|
58
|
-
def self.find_cache(&block)
|
59
|
-
configuration.define_find_cache(&block)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Mount a route on a directory. This allows an application to have
|
63
|
-
# multiple served directories, each connected to different routes.
|
64
|
-
#
|
65
|
-
def self.mount(route, root_path, &block)
|
66
|
-
configuration.mount(route, root_path, &block)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
data/lib/serve/rails/mount.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Serve
|
2
|
-
module Rails
|
3
|
-
class Mount # :nodoc:
|
4
|
-
attr_reader :root_path, :route
|
5
|
-
|
6
|
-
def initialize(route, root)
|
7
|
-
@route, @root_path = route, root
|
8
|
-
@view_helper_module_names = []
|
9
|
-
end
|
10
|
-
|
11
|
-
# Appends to the collection of view helpers that will be made availabe
|
12
|
-
# to the DynamicHandler. These should be module names. They will be
|
13
|
-
# constantized in order to allow for re-loading in development mode.
|
14
|
-
#
|
15
|
-
def append_view_helper(module_name)
|
16
|
-
@view_helper_module_names << module_name
|
17
|
-
end
|
18
|
-
|
19
|
-
def connection
|
20
|
-
@route == '/' ? '*path' : "#{@route}/*path"
|
21
|
-
end
|
22
|
-
|
23
|
-
def resolve_path(path)
|
24
|
-
Serve.resolve_file(@root_path, path)
|
25
|
-
end
|
26
|
-
|
27
|
-
def view_helpers
|
28
|
-
helpers = Module.new
|
29
|
-
@view_helper_module_names.each do |module_name|
|
30
|
-
helpers.module_eval do
|
31
|
-
include module_name.constantize
|
32
|
-
end
|
33
|
-
end
|
34
|
-
helpers
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/serve/rails/routing.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Serve
|
2
|
-
module Rails
|
3
|
-
module Routing
|
4
|
-
|
5
|
-
module MapperExtensions
|
6
|
-
def serve
|
7
|
-
serve_mounts = Serve::Rails.configuration.mounts
|
8
|
-
default_site_path = File.join(::Rails.root, 'site')
|
9
|
-
|
10
|
-
if File.directory?(default_site_path) && !serve_mounts.detect {|m| m.route == '/'}
|
11
|
-
mount('/', default_site_path)
|
12
|
-
end
|
13
|
-
|
14
|
-
serve_mounts.each do |mount|
|
15
|
-
@set.add_route(mount.connection, {
|
16
|
-
:controller => 'serve', :action => 'show',
|
17
|
-
:serve_route => mount.route
|
18
|
-
})
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Serve
|
2
|
-
module Rails
|
3
|
-
|
4
|
-
module ServeController
|
5
|
-
def show
|
6
|
-
response.headers.delete('Cache-Control')
|
7
|
-
cache = Serve::Rails.cache(request)
|
8
|
-
if cache.response_cached?(request.path)
|
9
|
-
cache.update_response(request.path, response, request)
|
10
|
-
else
|
11
|
-
mount = Serve::Rails.configuration.mounts.detect {|m| m.route == params[:serve_route]}
|
12
|
-
if path = mount.resolve_path(params[:path] || '/')
|
13
|
-
handler_class = Serve::FileTypeHandler.find(path)
|
14
|
-
handler = handler_class.new(mount.root_path, path)
|
15
|
-
install_view_helpers(handler, mount.view_helpers) if handler_class == Serve::DynamicHandler
|
16
|
-
handler.process(request, response)
|
17
|
-
cache.cache_response(request.path, response)
|
18
|
-
else
|
19
|
-
render_not_found
|
20
|
-
end
|
21
|
-
end
|
22
|
-
@performed_render = true
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def render_not_found
|
27
|
-
render :text => 'not found', :status => 404
|
28
|
-
end
|
29
|
-
|
30
|
-
# This is a quick solution: We need to install the view helpers defined by
|
31
|
-
# the Rails application after those of the Serve'd app's view helpers, so
|
32
|
-
# that those of the Rails application override them.
|
33
|
-
#
|
34
|
-
# Ideally, we'll work toward moving some of this Rails stuff further up
|
35
|
-
# into Serve, so that a simple Serve'd directory uses almost all of the
|
36
|
-
# same code, like the Configuration.
|
37
|
-
#
|
38
|
-
def install_view_helpers(handler, view_helpers)
|
39
|
-
controller = self
|
40
|
-
handler.singleton_class.module_eval do
|
41
|
-
define_method :install_view_helpers do |context|
|
42
|
-
super(context)
|
43
|
-
# Make available to view helpers
|
44
|
-
context.instance_variable_set('@controller', controller)
|
45
|
-
context.extend view_helpers
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
data/lib/serve/response_cache.rb
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
# This code and it's tests are adapted from the Radiant CMS project.
|
2
|
-
|
3
|
-
require 'uri'
|
4
|
-
|
5
|
-
module Serve
|
6
|
-
class ResponseCache
|
7
|
-
@@defaults = {
|
8
|
-
:expire_time => 5.minutes,
|
9
|
-
:default_extension => '.yml',
|
10
|
-
:perform_caching => true,
|
11
|
-
:use_x_sendfile => false
|
12
|
-
}
|
13
|
-
cattr_accessor :defaults
|
14
|
-
|
15
|
-
attr_accessor :directory, :expire_time, :default_extension, :perform_caching, :logger, :use_x_sendfile
|
16
|
-
alias :page_cache_directory :directory
|
17
|
-
alias :page_cache_extension :default_extension
|
18
|
-
private :page_cache_directory, :page_cache_extension
|
19
|
-
|
20
|
-
# Creates a ResponseCache object with the specified options.
|
21
|
-
#
|
22
|
-
# Options are as follows:
|
23
|
-
# :directory :: the path to the temporary cache directory
|
24
|
-
# :expire_time :: the number of seconds a cached response is considered valid (defaults to 5 min)
|
25
|
-
# :default_extension :: the extension cached files should use (defaults to '.yml')
|
26
|
-
# :perform_caching :: boolean value that turns caching on or off (defaults to true)
|
27
|
-
# :logger :: the application logging object
|
28
|
-
# :use_x_sendfile :: use X-Sendfile headers to speed up transfer of cached pages (not available on all web servers)
|
29
|
-
#
|
30
|
-
def initialize(options = {})
|
31
|
-
options = options.symbolize_keys.reverse_merge(defaults)
|
32
|
-
self.directory = options[:directory]
|
33
|
-
self.expire_time = options[:expire_time]
|
34
|
-
self.default_extension = options[:default_extension]
|
35
|
-
self.perform_caching = options[:perform_caching]
|
36
|
-
self.logger = options[:logger]
|
37
|
-
self.use_x_sendfile = options[:use_x_sendfile]
|
38
|
-
end
|
39
|
-
|
40
|
-
# Caches a response object for path to disk.
|
41
|
-
def cache_response(path, response)
|
42
|
-
if perform_caching
|
43
|
-
path = clean(path)
|
44
|
-
write_response(path, response)
|
45
|
-
end
|
46
|
-
response
|
47
|
-
end
|
48
|
-
|
49
|
-
# If perform_caching is set to true, updates a response object so that it mirrors the
|
50
|
-
# cached version. The request object is required to perform Last-Modified/If-Modified-Since
|
51
|
-
# checks--it is left optional to allow for backwards compatability.
|
52
|
-
def update_response(path, response, request=nil)
|
53
|
-
if perform_caching
|
54
|
-
path = clean(path)
|
55
|
-
read_response(path, response, request)
|
56
|
-
end
|
57
|
-
response
|
58
|
-
end
|
59
|
-
|
60
|
-
# Returns metadata for path.
|
61
|
-
def read_metadata(path)
|
62
|
-
path = clean(path)
|
63
|
-
name = "#{page_cache_path(path)}.yml"
|
64
|
-
if File.exists?(name) and not File.directory?(name)
|
65
|
-
content = File.open(name, "rb") { |f| f.read }
|
66
|
-
metadata = YAML::load(content)
|
67
|
-
metadata if metadata['expires'] >= Time.now
|
68
|
-
end
|
69
|
-
rescue
|
70
|
-
nil
|
71
|
-
end
|
72
|
-
|
73
|
-
# Returns true if a response is cached at the specified path.
|
74
|
-
def response_cached?(path)
|
75
|
-
perform_caching && !!read_metadata(path)
|
76
|
-
end
|
77
|
-
|
78
|
-
# Expires the cached response for the specified path.
|
79
|
-
def expire_response(path)
|
80
|
-
path = clean(path)
|
81
|
-
expire_page(path)
|
82
|
-
end
|
83
|
-
|
84
|
-
# Expires the entire cache.
|
85
|
-
def clear
|
86
|
-
Dir["#{directory}/*"].each do |f|
|
87
|
-
FileUtils.rm_rf f
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
# Ensures that path begins with a slash and remove extra slashes.
|
93
|
-
def clean(path)
|
94
|
-
path = path.gsub(%r{/+}, '/')
|
95
|
-
%r{^/?(.*?)/?$}.match(path)
|
96
|
-
"/#{$1}"
|
97
|
-
end
|
98
|
-
|
99
|
-
# Reads a cached response from disk and updates a response object.
|
100
|
-
def read_response(path, response, request)
|
101
|
-
file_path = page_cache_path(path)
|
102
|
-
if metadata = read_metadata(path)
|
103
|
-
response.headers.merge!(metadata['headers'] || {})
|
104
|
-
if client_has_cache?(metadata, request)
|
105
|
-
response.headers.merge!('Status' => '304 Not Modified')
|
106
|
-
elsif use_x_sendfile
|
107
|
-
response.headers.merge!('X-Sendfile' => "#{file_path}.data")
|
108
|
-
else
|
109
|
-
response.body = File.open("#{file_path}.data", "rb") {|f| f.read}
|
110
|
-
end
|
111
|
-
end
|
112
|
-
response
|
113
|
-
end
|
114
|
-
|
115
|
-
def client_has_cache?(metadata, request)
|
116
|
-
return false unless request
|
117
|
-
request_time = Time.httpdate(request.env["HTTP_IF_MODIFIED_SINCE"]) rescue nil
|
118
|
-
response_time = Time.httpdate(metadata['headers']['Last-Modified']) rescue nil
|
119
|
-
return request_time && response_time && response_time <= request_time
|
120
|
-
end
|
121
|
-
|
122
|
-
# Writes a response to disk.
|
123
|
-
def write_response(path, response)
|
124
|
-
if response.cache_timeout
|
125
|
-
if Time === response.cache_timeout
|
126
|
-
expires = response.cache_timeout
|
127
|
-
else
|
128
|
-
expires = Time.now + response.cache_timeout
|
129
|
-
end
|
130
|
-
else
|
131
|
-
expires = Time.now + self.expire_time
|
132
|
-
end
|
133
|
-
response.headers['Last-Modified'] ||= Time.now.httpdate
|
134
|
-
metadata = {
|
135
|
-
'headers' => response.headers,
|
136
|
-
'expires' => expires
|
137
|
-
}.to_yaml
|
138
|
-
cache_page(metadata, response.body, path)
|
139
|
-
end
|
140
|
-
|
141
|
-
def page_cache_path(path)
|
142
|
-
path = (path.empty? || path == "/") ? "/_site-root" : URI.unescape(path)
|
143
|
-
root_dir = File.expand_path(page_cache_directory)
|
144
|
-
cache_path = File.expand_path(File.join(root_dir, path), root_dir)
|
145
|
-
cache_path if cache_path.index(root_dir) == 0
|
146
|
-
end
|
147
|
-
|
148
|
-
def expire_page(path)
|
149
|
-
return unless perform_caching
|
150
|
-
|
151
|
-
if path = page_cache_path(path)
|
152
|
-
File.delete("#{path}.yml") if File.exists?("#{path}.yml")
|
153
|
-
File.delete("#{path}.data") if File.exists?("#{path}.data")
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def cache_page(metadata, content, path)
|
158
|
-
return unless perform_caching
|
159
|
-
|
160
|
-
if path = page_cache_path(path)
|
161
|
-
FileUtils.makedirs(File.dirname(path))
|
162
|
-
#dont want yml without data
|
163
|
-
File.open("#{path}.data", "wb+") { |f| f.write(content) }
|
164
|
-
File.open("#{path}.yml", "wb+") { |f| f.write(metadata) }
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
NULL_CACHE = ResponseCache.new(:perform_caching => false)
|
170
|
-
end
|
data/spec/response_cache_spec.rb
DELETED
@@ -1,248 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
|
3
|
-
describe Serve::ResponseCache do
|
4
|
-
class SilentLogger
|
5
|
-
def method_missing(*args); end
|
6
|
-
end
|
7
|
-
|
8
|
-
class TestRequest < Struct.new(:body, :env)
|
9
|
-
end
|
10
|
-
|
11
|
-
class TestResponse < Struct.new(:body, :headers, :cache_timeout)
|
12
|
-
def initialize(body = '', headers = {})
|
13
|
-
self.body = body
|
14
|
-
self.headers = headers
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
before :all do
|
19
|
-
@dir = File.expand_path("#{File.expand_path(File.dirname(__FILE__))}/tmp/cache")
|
20
|
-
@baddir = File.expand_path("#{File.expand_path(File.dirname(__FILE__))}/tmp/badcache")
|
21
|
-
end
|
22
|
-
|
23
|
-
before :each do
|
24
|
-
FileUtils.rm_rf @baddir
|
25
|
-
@cache = Serve::ResponseCache.new(
|
26
|
-
:directory => @dir,
|
27
|
-
:perform_caching => true
|
28
|
-
)
|
29
|
-
@cache.clear
|
30
|
-
end
|
31
|
-
|
32
|
-
after :each do
|
33
|
-
FileUtils.rm_rf @dir if File.exists? @dir
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'should initialize with defaults' do
|
37
|
-
@cache = Serve::ResponseCache.new
|
38
|
-
@cache.expire_time.should == 5.minutes
|
39
|
-
@cache.default_extension.should == '.yml'
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should initialize with options' do
|
43
|
-
@cache = Serve::ResponseCache.new(
|
44
|
-
:directory => "test",
|
45
|
-
:expire_time => 5,
|
46
|
-
:default_extension => ".xhtml",
|
47
|
-
:perform_caching => false,
|
48
|
-
:logger => SilentLogger.new
|
49
|
-
)
|
50
|
-
@cache.directory.should == "test"
|
51
|
-
@cache.expire_time.should == 5
|
52
|
-
@cache.default_extension.should == ".xhtml"
|
53
|
-
@cache.perform_caching.should == false
|
54
|
-
@cache.logger.should be_kind_of(SilentLogger)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should cache response' do
|
58
|
-
['test/me', '/test/me', 'test/me/', '/test/me/', 'test//me'].each do |url|
|
59
|
-
@cache.clear
|
60
|
-
response = response('content', 'Last-Modified' => 'Tue, 27 Feb 2007 06:13:43 GMT')
|
61
|
-
response.cache_timeout = Time.gm(2007, 2, 8, 17, 37, 9)
|
62
|
-
@cache.cache_response(url, response)
|
63
|
-
name = "#{@dir}/test/me.yml"
|
64
|
-
File.exists?(name).should == true
|
65
|
-
file(name).should match("expires: 2007-02-08 17:37:09 Z")
|
66
|
-
data_name = "#{@dir}/test/me.data"
|
67
|
-
file(data_name).should == "content"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'cache response with extension' do
|
72
|
-
@cache.cache_response("styles.css", response('content'))
|
73
|
-
File.exists?("#{@dir}/styles.css.yml").should == true
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'cache response without caching' do
|
77
|
-
@cache.perform_caching = false
|
78
|
-
@cache.cache_response('test', response('content'))
|
79
|
-
File.exists?("#{@dir}/test.yml").should == false
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'update response' do
|
83
|
-
@cache.cache_response('/test/me', response('content'))
|
84
|
-
['test/me', '/test/me', 'test/me/', '/test/me/', 'test//me'].each do |url|
|
85
|
-
@cache.update_response(url, response, TestRequest).body.should == 'content'
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'update response nonexistant' do
|
90
|
-
@cache.update_response('nothing/here', response, TestRequest).body.should == ''
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'update response without caching' do
|
94
|
-
@cache.cache_response('/test/me', response('content'))
|
95
|
-
@cache.perform_caching = false
|
96
|
-
@cache.update_response('/test/me', response, TestRequest).body.should == ''
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'cache' do
|
100
|
-
result = @cache.cache_response('test', response('content', 'Content-Type' => 'text/plain'))
|
101
|
-
cached = @cache.update_response('test', response, TestRequest)
|
102
|
-
cached.body.should == 'content'
|
103
|
-
cached.headers['Content-Type'].should == 'text/plain'
|
104
|
-
result.should be_kind_of(TestResponse)
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'expire response' do
|
108
|
-
@cache.cache_response('test', response('content'))
|
109
|
-
@cache.expire_response('test')
|
110
|
-
@cache.update_response('test', response, TestRequest).body.should == ''
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'clear' do
|
114
|
-
@cache.cache_response('test1', response('content'))
|
115
|
-
@cache.cache_response('test2', response('content'))
|
116
|
-
Dir["#{@dir}/*"].size.should == 4
|
117
|
-
|
118
|
-
@cache.clear
|
119
|
-
Dir["#{@dir}/*"].size.should == 0
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'response_cached?' do
|
123
|
-
@cache.response_cached?('test').should == false
|
124
|
-
result = @cache.cache_response('test', response('content'))
|
125
|
-
@cache.response_cached?('test').should == true
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'response_cached? should not answer true when response is cached but preform_caching option is false' do
|
129
|
-
@cache.cache_response('test', response('content'))
|
130
|
-
@cache.perform_caching = false
|
131
|
-
@cache.response_cached?('test').should == false
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'response_cached? with timeout' do
|
135
|
-
@cache.expire_time = 1
|
136
|
-
result = @cache.cache_response('test', response('content'))
|
137
|
-
sleep 1.5
|
138
|
-
@cache.response_cached?('test').should == false
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'response_cached? timeout with response setting' do
|
142
|
-
@cache.expire_time = 1
|
143
|
-
response = response('content')
|
144
|
-
response.cache_timeout = 3.seconds
|
145
|
-
result = @cache.cache_response('test', response)
|
146
|
-
sleep 1.5
|
147
|
-
@cache.response_cached?('test').should == true
|
148
|
-
sleep 2
|
149
|
-
@cache.response_cached?('test').should == false
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'send using x_sendfile header' do
|
153
|
-
@cache.use_x_sendfile = true
|
154
|
-
result = @cache.cache_response('test', response('content', 'Content-Type' => 'text/plain'))
|
155
|
-
cached = @cache.update_response('test', response, TestRequest)
|
156
|
-
cached.body.should == ''
|
157
|
-
cached.headers['X-Sendfile'].should == "#{@dir}/test.data"
|
158
|
-
cached.headers['Content-Type'].should == 'text/plain'
|
159
|
-
result.should be_kind_of(TestResponse)
|
160
|
-
end
|
161
|
-
|
162
|
-
it 'send cached page with last modified' do
|
163
|
-
last_modified = Time.now.httpdate
|
164
|
-
result = @cache.cache_response('test', response('content', 'Last-Modified' => last_modified))
|
165
|
-
request = TestRequest.new
|
166
|
-
request.env = { 'HTTP_IF_MODIFIED_SINCE' => last_modified }
|
167
|
-
second_call = @cache.update_response('test', response, request)
|
168
|
-
second_call.headers['Status'].should match(/^304/)
|
169
|
-
second_call.body.should == ''
|
170
|
-
result.should be_kind_of(TestResponse)
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'send cached page with old last modified' do
|
174
|
-
last_modified = Time.now.httpdate
|
175
|
-
result = @cache.cache_response('test', response('content', 'Last-Modified' => last_modified))
|
176
|
-
request = TestRequest.new
|
177
|
-
request.env = { 'HTTP_IF_MODIFIED_SINCE' => 5.minutes.ago.httpdate }
|
178
|
-
second_call = @cache.update_response('test', response, request)
|
179
|
-
second_call.body.should == 'content'
|
180
|
-
result.should be_kind_of(TestResponse)
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'not cached if metadata empty' do
|
184
|
-
FileUtils.makedirs(@dir)
|
185
|
-
File.open("#{@dir}/test_me.yml", 'w') { }
|
186
|
-
@cache.response_cached?('/test_me').should == false
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'not cached if metadata broken' do
|
190
|
-
FileUtils.makedirs(@dir)
|
191
|
-
File.open("#{@dir}/test_me.yml", 'w') {|f| f.puts '::: bad yaml file:::' }
|
192
|
-
@cache.response_cached?('/test_me').should == false
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'not cached if metadata not hash' do
|
196
|
-
FileUtils.makedirs(@dir)
|
197
|
-
File.open("#{@dir}/test_me.yml", 'w') {|f| f.puts ':symbol' }
|
198
|
-
@cache.response_cached?('/test_me').should == false
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'not cached if metadata has no expire' do
|
202
|
-
FileUtils.makedirs(@dir)
|
203
|
-
File.open("#{@dir}/test_me.yml", 'w') { |f| f.puts "--- \nheaders: \n Last-Modified: Tue, 27 Feb 2007 06:13:43 GMT\n" }
|
204
|
-
@cache.response_cached?('/test_me').should == false
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'cache cant write outside dir' do
|
208
|
-
@cache.cache_response('../badcache/cache_cant_write_outside_dir', response('content'))
|
209
|
-
File.exist?("#{@baddir}/cache_cant_write_outside_dir.yml").should == false
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'cache cannot read outside dir' do
|
213
|
-
FileUtils.makedirs(@baddir)
|
214
|
-
@cache.cache_response('/test_me', response('content'))
|
215
|
-
File.rename "#{@dir}/test_me.yml", "#{@baddir}/test_me.yml"
|
216
|
-
File.rename "#{@dir}/test_me.data", "#{@baddir}/test_me.data"
|
217
|
-
@cache.response_cached?('/../badcache/test_me').should == false
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'cache cannot expire outside dir' do
|
221
|
-
FileUtils.makedirs(@baddir)
|
222
|
-
@cache.cache_response('/test_me', response('content'))
|
223
|
-
File.rename "#{@dir}/test_me.yml", "#{@baddir}/test_me.yml"
|
224
|
-
File.rename "#{@dir}/test_me.data", "#{@baddir}/test_me.data"
|
225
|
-
@cache.expire_response('/../badcache/test_me')
|
226
|
-
File.exist?("#{@baddir}/test_me.yml").should == true
|
227
|
-
File.exist?("#{@baddir}/test_me.data").should == true
|
228
|
-
end
|
229
|
-
|
230
|
-
it 'should store indexes correctly' do
|
231
|
-
@cache.cache_response('/', response('content'))
|
232
|
-
@cache.response_cached?('_site-root').should == true
|
233
|
-
@cache.response_cached?('/') .should == true
|
234
|
-
File.exist?("#{@dir}/../cache.yml").should == false
|
235
|
-
File.exist?("#{@dir}/../cache.data").should == false
|
236
|
-
end
|
237
|
-
|
238
|
-
private
|
239
|
-
|
240
|
-
def file(filename)
|
241
|
-
open(filename) { |f| f.read } rescue ''
|
242
|
-
end
|
243
|
-
|
244
|
-
def response(*args)
|
245
|
-
TestResponse.new(*args)
|
246
|
-
end
|
247
|
-
|
248
|
-
end
|