joe-merb-core 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +992 -0
- data/CONTRIBUTORS +94 -0
- data/LICENSE +20 -0
- data/PUBLIC_CHANGELOG +142 -0
- data/README +21 -0
- data/Rakefile +456 -0
- data/TODO +0 -0
- data/bin/merb +11 -0
- data/bin/merb-specs +5 -0
- data/lib/merb-core.rb +648 -0
- data/lib/merb-core/autoload.rb +31 -0
- data/lib/merb-core/bootloader.rb +889 -0
- data/lib/merb-core/config.rb +380 -0
- data/lib/merb-core/constants.rb +45 -0
- data/lib/merb-core/controller/abstract_controller.rb +620 -0
- data/lib/merb-core/controller/exceptions.rb +302 -0
- data/lib/merb-core/controller/merb_controller.rb +283 -0
- data/lib/merb-core/controller/mime.rb +111 -0
- data/lib/merb-core/controller/mixins/authentication.rb +123 -0
- data/lib/merb-core/controller/mixins/conditional_get.rb +83 -0
- data/lib/merb-core/controller/mixins/controller.rb +316 -0
- data/lib/merb-core/controller/mixins/render.rb +513 -0
- data/lib/merb-core/controller/mixins/responder.rb +469 -0
- data/lib/merb-core/controller/template.rb +254 -0
- data/lib/merb-core/core_ext.rb +9 -0
- data/lib/merb-core/core_ext/hash.rb +7 -0
- data/lib/merb-core/core_ext/kernel.rb +345 -0
- data/lib/merb-core/dispatch/cookies.rb +130 -0
- data/lib/merb-core/dispatch/default_exception/default_exception.rb +93 -0
- data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +200 -0
- data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +77 -0
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +98 -0
- data/lib/merb-core/dispatch/dispatcher.rb +172 -0
- data/lib/merb-core/dispatch/request.rb +718 -0
- data/lib/merb-core/dispatch/router.rb +228 -0
- data/lib/merb-core/dispatch/router/behavior.rb +610 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/resources.rb +220 -0
- data/lib/merb-core/dispatch/router/route.rb +560 -0
- data/lib/merb-core/dispatch/session.rb +222 -0
- data/lib/merb-core/dispatch/session/container.rb +74 -0
- data/lib/merb-core/dispatch/session/cookie.rb +173 -0
- data/lib/merb-core/dispatch/session/memcached.rb +68 -0
- data/lib/merb-core/dispatch/session/memory.rb +99 -0
- data/lib/merb-core/dispatch/session/store_container.rb +150 -0
- data/lib/merb-core/dispatch/worker.rb +28 -0
- data/lib/merb-core/gem_ext/erubis.rb +77 -0
- data/lib/merb-core/logger.rb +215 -0
- data/lib/merb-core/plugins.rb +67 -0
- data/lib/merb-core/rack.rb +27 -0
- data/lib/merb-core/rack/adapter.rb +47 -0
- data/lib/merb-core/rack/adapter/ebb.rb +24 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +13 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
- data/lib/merb-core/rack/adapter/irb.rb +119 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +33 -0
- data/lib/merb-core/rack/adapter/runner.rb +28 -0
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +14 -0
- data/lib/merb-core/rack/adapter/thin.rb +40 -0
- data/lib/merb-core/rack/adapter/thin_turbo.rb +17 -0
- data/lib/merb-core/rack/adapter/webrick.rb +72 -0
- data/lib/merb-core/rack/application.rb +32 -0
- data/lib/merb-core/rack/handler/mongrel.rb +96 -0
- data/lib/merb-core/rack/middleware.rb +20 -0
- data/lib/merb-core/rack/middleware/conditional_get.rb +29 -0
- data/lib/merb-core/rack/middleware/content_length.rb +18 -0
- data/lib/merb-core/rack/middleware/csrf.rb +73 -0
- data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
- data/lib/merb-core/rack/middleware/profiler.rb +19 -0
- data/lib/merb-core/rack/middleware/static.rb +45 -0
- data/lib/merb-core/rack/middleware/tracer.rb +20 -0
- data/lib/merb-core/server.rb +321 -0
- data/lib/merb-core/tasks/audit.rake +68 -0
- data/lib/merb-core/tasks/gem_management.rb +252 -0
- data/lib/merb-core/tasks/merb.rb +2 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +51 -0
- data/lib/merb-core/tasks/stats.rake +71 -0
- data/lib/merb-core/test.rb +17 -0
- data/lib/merb-core/test/helpers.rb +10 -0
- data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +176 -0
- data/lib/merb-core/test/helpers/request_helper.rb +61 -0
- data/lib/merb-core/test/helpers/route_helper.rb +47 -0
- data/lib/merb-core/test/helpers/view_helper.rb +121 -0
- data/lib/merb-core/test/matchers.rb +10 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +108 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +137 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +393 -0
- data/lib/merb-core/test/run_specs.rb +141 -0
- data/lib/merb-core/test/tasks/spectasks.rb +68 -0
- data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
- data/lib/merb-core/test/test_ext/object.rb +14 -0
- data/lib/merb-core/test/test_ext/string.rb +14 -0
- data/lib/merb-core/vendor/facets.rb +2 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
- data/lib/merb-core/vendor/facets/inflect.rb +342 -0
- data/lib/merb-core/version.rb +3 -0
- metadata +253 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require "thin-turbo"
|
2
|
+
|
3
|
+
module Merb
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
|
7
|
+
class ThinTurbo < Thin
|
8
|
+
# start a Thin Turbo server on given host and port.
|
9
|
+
|
10
|
+
def self.new_server(port)
|
11
|
+
@opts.merge!(:backend => ::Thin::Backends::Turbo)
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'webrick/utils'
|
3
|
+
require 'rack/handler/webrick'
|
4
|
+
module Merb
|
5
|
+
module Rack
|
6
|
+
|
7
|
+
class WEBrick < Merb::Rack::AbstractAdapter
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :server
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.new_server(port)
|
14
|
+
options = {
|
15
|
+
:Port => port,
|
16
|
+
:BindAddress => @opts[:host],
|
17
|
+
:Logger => Merb.logger,
|
18
|
+
:AccessLog => [
|
19
|
+
[Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
20
|
+
[Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
21
|
+
]
|
22
|
+
}
|
23
|
+
|
24
|
+
sockets = ::WEBrick::Utils.create_listeners nil, port
|
25
|
+
@server = ::WEBrick::HTTPServer.new(options.merge(:DoNotListen => true))
|
26
|
+
@server.listeners.replace sockets
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.start_server
|
30
|
+
@server.mount("/", ::Rack::Handler::WEBrick, @opts[:app])
|
31
|
+
@server.start
|
32
|
+
exit(@status)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.stop(status = 0)
|
36
|
+
@status = status
|
37
|
+
@server.shutdown
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.exit_process(status = 0)
|
41
|
+
end
|
42
|
+
|
43
|
+
# start WEBrick server on given host and port.
|
44
|
+
|
45
|
+
# ==== Parameters
|
46
|
+
# opts<Hash>:: Options for WEBrick (see below).
|
47
|
+
#
|
48
|
+
# ==== Options (opts)
|
49
|
+
# :host<String>:: The hostname that WEBrick should serve.
|
50
|
+
# :port<Fixnum>:: The port WEBrick should bind to.
|
51
|
+
# :app<String>>:: The application name.
|
52
|
+
# def self.start(opts={})
|
53
|
+
# Merb.logger.warn!("Using Webrick adapter")
|
54
|
+
#
|
55
|
+
# options = {
|
56
|
+
# :Port => opts[:port],
|
57
|
+
# :BindAddress => opts[:host],
|
58
|
+
# :Logger => Merb.logger,
|
59
|
+
# :AccessLog => [
|
60
|
+
# [Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
61
|
+
# [Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
62
|
+
# ]
|
63
|
+
# }
|
64
|
+
#
|
65
|
+
# server = ::WEBrick::HTTPServer.new(options)
|
66
|
+
# Merb::Server.change_privilege
|
67
|
+
# server.mount("/", ::Rack::Handler::WEBrick, opts[:app])
|
68
|
+
# server.start
|
69
|
+
# end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Application
|
4
|
+
|
5
|
+
def call(env)
|
6
|
+
begin
|
7
|
+
controller = ::Merb::Dispatcher.handle(Merb::Request.new(env))
|
8
|
+
rescue Object => e
|
9
|
+
return [500, {Merb::Const::CONTENT_TYPE => "text/html"}, e.message + "<br/>" + e.backtrace.join("<br/>")]
|
10
|
+
end
|
11
|
+
Merb.logger.info "\n\n"
|
12
|
+
Merb.logger.flush
|
13
|
+
|
14
|
+
# unless controller.headers[Merb::Const::DATE]
|
15
|
+
# require "time"
|
16
|
+
# controller.headers[Merb::Const::DATE] = Time.now.rfc2822.to_s
|
17
|
+
# end
|
18
|
+
controller.rack_response
|
19
|
+
end
|
20
|
+
|
21
|
+
def deferred?(env)
|
22
|
+
path = env[Merb::Const::PATH_INFO] ? env[Merb::Const::PATH_INFO].chomp('/') : ""
|
23
|
+
if path =~ Merb.deferred_actions
|
24
|
+
Merb.logger.info! "Deferring Request: #{path}"
|
25
|
+
true
|
26
|
+
else
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end # deferred?(env)
|
30
|
+
end # Application
|
31
|
+
end # Rack
|
32
|
+
end # Merb
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
class Mongrel::HttpResponse
|
3
|
+
NO_CLOSE_STATUS_FORMAT = "HTTP/1.1 %d %s\r\n".freeze
|
4
|
+
|
5
|
+
# Sends the status to the client without closing the connection.
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# content_length<Fixnum>:: The length of the content. Defaults to body length.
|
9
|
+
def send_status_no_connection_close(content_length=@body.length)
|
10
|
+
unless @status_sent
|
11
|
+
write(NO_CLOSE_STATUS_FORMAT % [@status, Mongrel::HTTP_STATUS_CODES[@status]])
|
12
|
+
@status_sent = true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Merb
|
18
|
+
module Rack
|
19
|
+
module Handler
|
20
|
+
class Mongrel < ::Mongrel::HttpHandler
|
21
|
+
# Runs the server and yields it to a block.
|
22
|
+
#
|
23
|
+
# ==== Parameters
|
24
|
+
# app<Merb::Rack::Application>:: The app that Mongrel should handle.
|
25
|
+
# options<Hash>:: Options to pass to Mongrel (see below).
|
26
|
+
#
|
27
|
+
# ==== Block parameters
|
28
|
+
# server<Mongrel::HttpServer>:: The server to run.
|
29
|
+
#
|
30
|
+
# ==== Options (options)
|
31
|
+
# :Host<String>::
|
32
|
+
# The hostname on which the app should run. Defaults to "0.0.0.0"
|
33
|
+
# :Port<Fixnum>:: The port for the app. Defaults to 8080.
|
34
|
+
def self.run(app, options={})
|
35
|
+
@server = ::Mongrel::HttpServer.new(options[:Host] || '0.0.0.0',
|
36
|
+
options[:Port] || 8080)
|
37
|
+
@server.register('/', ::Merb::Rack::Handler::Mongrel.new(app))
|
38
|
+
yield @server if block_given?
|
39
|
+
@server.run.join
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.stop(block = true)
|
43
|
+
@server.stop
|
44
|
+
end
|
45
|
+
|
46
|
+
# ==== Parameters
|
47
|
+
# app<Merb::Rack::Application>:: The app that Mongrel should handle.
|
48
|
+
def initialize(app)
|
49
|
+
@app = app
|
50
|
+
end
|
51
|
+
|
52
|
+
# ==== Parameters
|
53
|
+
# request<Merb::Request>:: The HTTP request to handle.
|
54
|
+
# response<HTTPResponse>:: The response object to write response to.
|
55
|
+
def process(request, response)
|
56
|
+
env = {}.replace(request.params)
|
57
|
+
env.delete "HTTP_CONTENT_TYPE"
|
58
|
+
env.delete "HTTP_CONTENT_LENGTH"
|
59
|
+
|
60
|
+
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
61
|
+
|
62
|
+
env.update({"rack.version" => [0,1],
|
63
|
+
"rack.input" => request.body || StringIO.new(""),
|
64
|
+
"rack.errors" => STDERR,
|
65
|
+
|
66
|
+
"rack.multithread" => true,
|
67
|
+
"rack.multiprocess" => false, # ???
|
68
|
+
"rack.run_once" => false,
|
69
|
+
|
70
|
+
"rack.url_scheme" => "http"
|
71
|
+
})
|
72
|
+
env["QUERY_STRING"] ||= ""
|
73
|
+
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
|
74
|
+
|
75
|
+
status, headers, body = @app.call(env)
|
76
|
+
|
77
|
+
begin
|
78
|
+
response.status = status.to_i
|
79
|
+
headers.each { |k, vs|
|
80
|
+
vs.each { |v|
|
81
|
+
response.header[k] = v
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
body.each { |part|
|
86
|
+
response.body << part
|
87
|
+
}
|
88
|
+
response.finished
|
89
|
+
ensure
|
90
|
+
body.close if body.respond_to? :close
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
|
4
|
+
class ConditionalGet < Merb::Rack::Middleware
|
5
|
+
def call(env)
|
6
|
+
status, headers, body = @app.call(env)
|
7
|
+
|
8
|
+
if document_not_modified?(env, headers)
|
9
|
+
status = 304
|
10
|
+
body = ""
|
11
|
+
# set Date header using RFC1123 date format as specified by HTTP
|
12
|
+
# RFC2616 section 3.3.1.
|
13
|
+
end
|
14
|
+
|
15
|
+
[status, headers, body]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def document_not_modified?(env, headers)
|
20
|
+
if etag = headers[Merb::Const::ETAG]
|
21
|
+
etag == env[Merb::Const::HTTP_IF_NONE_MATCH]
|
22
|
+
elsif last_modified = headers[Merb::Const::LAST_MODIFIED]
|
23
|
+
last_modified == env[Merb::Const::HTTP_IF_MODIFIED_SINCE]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
|
4
|
+
class ContentLength < Merb::Rack::Middleware
|
5
|
+
def call(env)
|
6
|
+
status, headers, body = @app.call(env)
|
7
|
+
|
8
|
+
# to_s is because Rack spec expects header
|
9
|
+
# values to be iterable and yield strings
|
10
|
+
header = 'Content-Length'.freeze
|
11
|
+
headers[header] = body.size.to_s unless headers.has_key?(header)
|
12
|
+
|
13
|
+
[status, headers, body]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Merb
|
4
|
+
module Rack
|
5
|
+
|
6
|
+
class Csrf < Merb::Rack::Middleware
|
7
|
+
HTML_TYPES = %w(text/html application/xhtml+xml)
|
8
|
+
POST_FORM_RE = Regexp.compile('(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', Regexp::IGNORECASE)
|
9
|
+
ERROR_MSG = '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>'.freeze
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
status, header, body = @app.call(env)
|
13
|
+
body = body.to_s
|
14
|
+
if env[Merb::Const::REQUEST_METHOD] == Merb::Const::GET
|
15
|
+
body = process_response(body) if valid_content_type?(header[Merb::Const::CONTENT_TYPE])
|
16
|
+
elsif env[Merb::Const::REQUEST_METHOD] == Merb::Const::POST
|
17
|
+
status, body = process_request(env, status, body)
|
18
|
+
end
|
19
|
+
|
20
|
+
[status, header, body]
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def process_request(env, status, body)
|
25
|
+
session_id = Merb::Config[:session_id_key]
|
26
|
+
csrf_token = _make_token(session_id)
|
27
|
+
|
28
|
+
request_csrf_token = env['csrf_authentication_token']
|
29
|
+
|
30
|
+
unless csrf_token == request_csrf_token
|
31
|
+
exception = Merb::ControllerExceptions::Forbidden.new(ERROR_MSG)
|
32
|
+
status = exception.status
|
33
|
+
body = exception.message
|
34
|
+
|
35
|
+
return [status, body]
|
36
|
+
end
|
37
|
+
|
38
|
+
return [status, body]
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_response(body)
|
42
|
+
session_id = Merb::Config[:session_id_key]
|
43
|
+
csrf_token = _make_token(session_id)
|
44
|
+
|
45
|
+
if csrf_token
|
46
|
+
modified_body = ''
|
47
|
+
body.scan(POST_FORM_RE) do |match|
|
48
|
+
modified_body << add_csrf_field($~, csrf_token)
|
49
|
+
end
|
50
|
+
|
51
|
+
body = modified_body
|
52
|
+
end
|
53
|
+
|
54
|
+
body
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_csrf_field(match, csrf_token)
|
58
|
+
modified_body = match.pre_match
|
59
|
+
modified_body << match.to_s
|
60
|
+
modified_body << "<div style='display: none;'><input type='hidden' id='csrf_authentication_token' name='csrf_authentication_token' value='#{csrf_token}' /></div>"
|
61
|
+
modified_body << match.post_match
|
62
|
+
end
|
63
|
+
|
64
|
+
def valid_content_type?(content_type)
|
65
|
+
HTML_TYPES.include?(content_type.split(';').first)
|
66
|
+
end
|
67
|
+
|
68
|
+
def _make_token(session_id)
|
69
|
+
Digest::MD5.hexdigest(Merb::Config[:session_secret_key] + session_id)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class PathPrefix < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app, path_prefix = nil)
|
6
|
+
super(app)
|
7
|
+
@path_prefix = /^#{Regexp.escape(path_prefix)}/
|
8
|
+
end
|
9
|
+
|
10
|
+
def deferred?(env)
|
11
|
+
strip_path_prefix(env)
|
12
|
+
@app.deferred?(env)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
strip_path_prefix(env)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def strip_path_prefix(env)
|
21
|
+
['PATH_INFO', 'REQUEST_URI'].each do |path_key|
|
22
|
+
if env[path_key] =~ @path_prefix
|
23
|
+
env[path_key].sub!(@path_prefix, '')
|
24
|
+
env[path_key] = '/' if env[path_key].empty?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Profiler < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app, min=1, iter=1)
|
6
|
+
super(app)
|
7
|
+
@min, @iter = min, iter
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
__profile__("profile_output", @min, @iter) do
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Static < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def initialize(app,directory)
|
6
|
+
super(app)
|
7
|
+
@static_server = ::Rack::File.new(directory)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
path = env['PATH_INFO'] ? env['PATH_INFO'].chomp('/') : ""
|
12
|
+
cached_path = (path.empty? ? 'index' : path) + '.html'
|
13
|
+
|
14
|
+
if file_exist?(path) && env['REQUEST_METHOD'] =~ /GET|HEAD/ # Serve the file if it's there and the request method is GET or HEAD
|
15
|
+
serve_static(env)
|
16
|
+
elsif file_exist?(cached_path) && env['REQUEST_METHOD'] =~ /GET|HEAD/ # Serve the page cache if it's there and the request method is GET or HEAD
|
17
|
+
env['PATH_INFO'] = cached_path
|
18
|
+
serve_static(env)
|
19
|
+
elsif path =~ /favicon\.ico/
|
20
|
+
return [404, {"Content-Type"=>"text/html"}, "404 Not Found."]
|
21
|
+
else
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# ==== Parameters
|
27
|
+
# path<String>:: The path to the file relative to the server root.
|
28
|
+
#
|
29
|
+
# ==== Returns
|
30
|
+
# Boolean:: True if file exists under the server root and is readable.
|
31
|
+
def file_exist?(path)
|
32
|
+
full_path = ::File.join(@static_server.root, ::Merb::Request.unescape(path))
|
33
|
+
::File.file?(full_path) && ::File.readable?(full_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
# ==== Parameters
|
37
|
+
# env<Hash>:: Environment variables to pass on to the server.
|
38
|
+
def serve_static(env)
|
39
|
+
env["PATH_INFO"] = ::Merb::Request.unescape(env["PATH_INFO"])
|
40
|
+
@static_server.call(env)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|