wycats-merb-core 0.9.8
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 +992 -0
- data/CONTRIBUTORS +94 -0
- data/LICENSE +20 -0
- data/PUBLIC_CHANGELOG +142 -0
- data/README +21 -0
- data/Rakefile +458 -0
- data/TODO +0 -0
- data/bin/merb +11 -0
- data/bin/merb-specs +5 -0
- data/lib/merb-core.rb +598 -0
- data/lib/merb-core/autoload.rb +31 -0
- data/lib/merb-core/bootloader.rb +717 -0
- data/lib/merb-core/config.rb +305 -0
- data/lib/merb-core/constants.rb +45 -0
- data/lib/merb-core/controller/abstract_controller.rb +568 -0
- data/lib/merb-core/controller/exceptions.rb +315 -0
- data/lib/merb-core/controller/merb_controller.rb +256 -0
- data/lib/merb-core/controller/mime.rb +107 -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 +319 -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 +340 -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 +198 -0
- data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +73 -0
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +94 -0
- data/lib/merb-core/dispatch/dispatcher.rb +176 -0
- data/lib/merb-core/dispatch/request.rb +729 -0
- data/lib/merb-core/dispatch/router.rb +151 -0
- data/lib/merb-core/dispatch/router/behavior.rb +566 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/resources.rb +191 -0
- data/lib/merb-core/dispatch/router/route.rb +511 -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 +203 -0
- data/lib/merb-core/plugins.rb +67 -0
- data/lib/merb-core/rack.rb +25 -0
- data/lib/merb-core/rack/adapter.rb +44 -0
- data/lib/merb-core/rack/adapter/ebb.rb +25 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
- data/lib/merb-core/rack/adapter/irb.rb +118 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/runner.rb +28 -0
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/thin.rb +39 -0
- data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
- data/lib/merb-core/rack/adapter/webrick.rb +36 -0
- data/lib/merb-core/rack/application.rb +32 -0
- data/lib/merb-core/rack/handler/mongrel.rb +97 -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 +284 -0
- data/lib/merb-core/tasks/audit.rake +68 -0
- data/lib/merb-core/tasks/gem_management.rb +229 -0
- data/lib/merb-core/tasks/merb.rb +1 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +80 -0
- data/lib/merb-core/tasks/stats.rake +71 -0
- data/lib/merb-core/test.rb +11 -0
- data/lib/merb-core/test/helpers.rb +9 -0
- data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
- data/lib/merb-core/test/helpers/request_helper.rb +393 -0
- data/lib/merb-core/test/helpers/route_helper.rb +39 -0
- data/lib/merb-core/test/helpers/view_helper.rb +121 -0
- data/lib/merb-core/test/matchers.rb +9 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +351 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +137 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +375 -0
- data/lib/merb-core/test/run_specs.rb +49 -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,24 @@
|
|
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
|
+
# ==== Parameters
|
11
|
+
# opts<Hash>:: Options for Thin Turbo (see below).
|
12
|
+
#
|
13
|
+
# ==== Options (opts)
|
14
|
+
# :host<String>:: The hostname that Thin Turbo should serve.
|
15
|
+
# :port<Fixnum>:: The port Thin Turbo should bind to.
|
16
|
+
# :socket<Fixnum>>:: The socket number that thin should bind to.
|
17
|
+
# :socket_file<String>>:: The socket file that thin should attach to.
|
18
|
+
# :app<String>>:: The application name.
|
19
|
+
def self.start(opts={})
|
20
|
+
super(opts.merge(:backend => ::Thin::Backends::Turbo))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'rack/handler/webrick'
|
3
|
+
module Merb
|
4
|
+
module Rack
|
5
|
+
|
6
|
+
class WEBrick
|
7
|
+
# start WEBrick server on given host and port.
|
8
|
+
|
9
|
+
# ==== Parameters
|
10
|
+
# opts<Hash>:: Options for WEBrick (see below).
|
11
|
+
#
|
12
|
+
# ==== Options (opts)
|
13
|
+
# :host<String>:: The hostname that WEBrick should serve.
|
14
|
+
# :port<Fixnum>:: The port WEBrick should bind to.
|
15
|
+
# :app<String>>:: The application name.
|
16
|
+
def self.start(opts={})
|
17
|
+
Merb.logger.warn!("Using Webrick adapter")
|
18
|
+
|
19
|
+
options = {
|
20
|
+
:Port => opts[:port],
|
21
|
+
:BindAddress => opts[:host],
|
22
|
+
:Logger => Merb.logger,
|
23
|
+
:AccessLog => [
|
24
|
+
[Merb.logger, ::WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
25
|
+
[Merb.logger, ::WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
26
|
+
]
|
27
|
+
}
|
28
|
+
|
29
|
+
server = ::WEBrick::HTTPServer.new(options)
|
30
|
+
Merb::Server.change_privilege
|
31
|
+
server.mount("/", ::Rack::Handler::WEBrick, opts[:app])
|
32
|
+
server.start
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
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,97 @@
|
|
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
|
+
# ==== Parameters
|
43
|
+
# app<Merb::Rack::Application>:: The app that Mongrel should handle.
|
44
|
+
def initialize(app)
|
45
|
+
@app = app
|
46
|
+
end
|
47
|
+
|
48
|
+
# ==== Parameters
|
49
|
+
# request<Merb::Request>:: The HTTP request to handle.
|
50
|
+
# response<HTTPResponse>:: The response object to write response to.
|
51
|
+
def process(request, response)
|
52
|
+
env = {}.replace(request.params)
|
53
|
+
env.delete "HTTP_CONTENT_TYPE"
|
54
|
+
env.delete "HTTP_CONTENT_LENGTH"
|
55
|
+
|
56
|
+
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
|
57
|
+
|
58
|
+
env.update({"rack.version" => [0,1],
|
59
|
+
"rack.input" => request.body || StringIO.new(""),
|
60
|
+
"rack.errors" => STDERR,
|
61
|
+
|
62
|
+
"rack.multithread" => true,
|
63
|
+
"rack.multiprocess" => false, # ???
|
64
|
+
"rack.run_once" => false,
|
65
|
+
|
66
|
+
"rack.url_scheme" => "http",
|
67
|
+
"rack.streaming" => true
|
68
|
+
})
|
69
|
+
env["QUERY_STRING"] ||= ""
|
70
|
+
env.delete "PATH_INFO" if env["PATH_INFO"] == ""
|
71
|
+
|
72
|
+
status, headers, body = @app.call(env)
|
73
|
+
|
74
|
+
begin
|
75
|
+
response.status = status.to_i
|
76
|
+
headers.each { |k, vs|
|
77
|
+
vs.each { |v|
|
78
|
+
response.header[k] = v
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
if Proc === body
|
83
|
+
body.call(response)
|
84
|
+
else
|
85
|
+
body.each { |part|
|
86
|
+
response.body << part
|
87
|
+
}
|
88
|
+
end
|
89
|
+
response.finished
|
90
|
+
ensure
|
91
|
+
body.close if body.respond_to? :close
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
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
|
+
|
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
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Merb
|
2
|
+
module Rack
|
3
|
+
class Tracer < Merb::Rack::Middleware
|
4
|
+
|
5
|
+
def call(env)
|
6
|
+
|
7
|
+
Merb.logger.debug!("Rack environment:\n" + env.inspect + "\n\n")
|
8
|
+
|
9
|
+
status, headers, body = @app.call(env)
|
10
|
+
|
11
|
+
Merb.logger.debug!("Status: #{status.inspect}")
|
12
|
+
Merb.logger.debug!("Headers: #{headers.inspect}")
|
13
|
+
Merb.logger.debug!("Body: #{body.inspect}")
|
14
|
+
|
15
|
+
[status, headers, body]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|