actionpack 3.2.19 → 4.2.11.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +412 -503
- data/MIT-LICENSE +1 -1
- data/README.rdoc +11 -294
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +52 -18
- data/lib/abstract_controller/callbacks.rb +87 -89
- data/lib/abstract_controller/collector.rb +17 -3
- data/lib/abstract_controller/helpers.rb +41 -14
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/rendering.rb +65 -118
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +7 -7
- data/lib/abstract_controller.rb +2 -10
- data/lib/action_controller/base.rb +61 -28
- data/lib/action_controller/caching/fragments.rb +30 -54
- data/lib/action_controller/caching.rb +38 -35
- data/lib/action_controller/log_subscriber.rb +35 -18
- data/lib/action_controller/metal/conditional_get.rb +103 -34
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +41 -9
- data/lib/action_controller/metal/force_ssl.rb +70 -12
- data/lib/action_controller/metal/head.rb +30 -7
- data/lib/action_controller/metal/helpers.rb +11 -11
- data/lib/action_controller/metal/hide_actions.rb +0 -1
- data/lib/action_controller/metal/http_authentication.rb +140 -94
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -7
- data/lib/action_controller/metal/live.rb +328 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -152
- data/lib/action_controller/metal/params_wrapper.rb +126 -81
- data/lib/action_controller/metal/rack_delegation.rb +10 -4
- data/lib/action_controller/metal/redirecting.rb +44 -41
- data/lib/action_controller/metal/renderers.rb +48 -19
- data/lib/action_controller/metal/rendering.rb +46 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +250 -29
- data/lib/action_controller/metal/streaming.rb +30 -38
- data/lib/action_controller/metal/strong_parameters.rb +669 -0
- data/lib/action_controller/metal/testing.rb +12 -18
- data/lib/action_controller/metal/url_for.rb +31 -29
- data/lib/action_controller/metal.rb +31 -40
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +38 -18
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/test_case.rb +359 -173
- data/lib/action_controller.rb +9 -16
- data/lib/action_dispatch/http/cache.rb +64 -11
- data/lib/action_dispatch/http/filter_parameters.rb +20 -10
- data/lib/action_dispatch/http/filter_redirect.rb +38 -0
- data/lib/action_dispatch/http/headers.rb +85 -17
- data/lib/action_dispatch/http/mime_negotiation.rb +55 -5
- data/lib/action_dispatch/http/mime_type.rb +167 -114
- data/lib/action_dispatch/http/mime_types.rb +2 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +30 -46
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +108 -45
- data/lib/action_dispatch/http/response.rb +247 -48
- data/lib/action_dispatch/http/upload.rb +60 -29
- data/lib/action_dispatch/http/url.rb +135 -45
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +166 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +47 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +157 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +128 -0
- data/lib/action_dispatch/journey/parser.rb +198 -0
- data/lib/action_dispatch/journey/parser.y +49 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +193 -0
- data/lib/action_dispatch/journey/route.rb +125 -0
- data/lib/action_dispatch/journey/router/strexp.rb +27 -0
- data/lib/action_dispatch/journey/router/utils.rb +93 -0
- data/lib/action_dispatch/journey/router.rb +144 -0
- data/lib/action_dispatch/journey/routes.rb +80 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +221 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/middleware/callbacks.rb +16 -11
- data/lib/action_dispatch/middleware/cookies.rb +346 -125
- data/lib/action_dispatch/middleware/debug_exceptions.rb +52 -24
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -9
- data/lib/action_dispatch/middleware/flash.rb +85 -72
- data/lib/action_dispatch/middleware/params_parser.rb +16 -31
- data/lib/action_dispatch/middleware/public_exceptions.rb +39 -14
- data/lib/action_dispatch/middleware/reloader.rb +16 -7
- data/lib/action_dispatch/middleware/remote_ip.rb +132 -40
- data/lib/action_dispatch/middleware/request_id.rb +3 -7
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +84 -29
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -44
- data/lib/action_dispatch/middleware/ssl.rb +72 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +80 -23
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +34 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +133 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +19 -6
- data/lib/action_dispatch/request/session.rb +193 -0
- data/lib/action_dispatch/request/utils.rb +35 -0
- data/lib/action_dispatch/routing/endpoint.rb +10 -0
- data/lib/action_dispatch/routing/inspector.rb +234 -0
- data/lib/action_dispatch/routing/mapper.rb +897 -436
- data/lib/action_dispatch/routing/polymorphic_routes.rb +213 -92
- data/lib/action_dispatch/routing/redirection.rb +97 -37
- data/lib/action_dispatch/routing/route_set.rb +432 -239
- data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
- data/lib/action_dispatch/routing/url_for.rb +63 -34
- data/lib/action_dispatch/routing.rb +57 -89
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -36
- data/lib/action_dispatch/testing/assertions/response.rb +24 -38
- data/lib/action_dispatch/testing/assertions/routing.rb +55 -54
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -434
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -137
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +88 -72
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +13 -9
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- data/lib/action_dispatch.rb +24 -21
- data/lib/action_pack/gem_version.rb +15 -0
- data/lib/action_pack/version.rb +5 -7
- data/lib/action_pack.rb +1 -1
- metadata +181 -292
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/integration_test.rb +0 -2
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/deprecated.rb +0 -3
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/responder.rb +0 -286
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_controller/record_identifier.rb +0 -85
- data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_controller/vendor/html-scanner.rb +0 -20
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/base.rb +0 -220
- data/lib/action_view/buffers.rb +0 -43
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/flows.rb +0 -79
- data/lib/action_view/helpers/active_model_helper.rb +0 -50
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
- data/lib/action_view/helpers/cache_helper.rb +0 -64
- data/lib/action_view/helpers/capture_helper.rb +0 -203
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1062
- data/lib/action_view/helpers/debug_helper.rb +0 -40
- data/lib/action_view/helpers/form_helper.rb +0 -1486
- data/lib/action_view/helpers/form_options_helper.rb +0 -658
- data/lib/action_view/helpers/form_tag_helper.rb +0 -685
- data/lib/action_view/helpers/javascript_helper.rb +0 -110
- data/lib/action_view/helpers/number_helper.rb +0 -622
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -111
- data/lib/action_view/helpers/rendering_helper.rb +0 -90
- data/lib/action_view/helpers/sanitize_helper.rb +0 -259
- data/lib/action_view/helpers/tag_helper.rb +0 -160
- data/lib/action_view/helpers/text_helper.rb +0 -426
- data/lib/action_view/helpers/translation_helper.rb +0 -91
- data/lib/action_view/helpers/url_helper.rb +0 -693
- data/lib/action_view/helpers.rb +0 -60
- data/lib/action_view/locale/en.yml +0 -160
- data/lib/action_view/log_subscriber.rb +0 -28
- data/lib/action_view/lookup_context.rb +0 -254
- data/lib/action_view/path_set.rb +0 -89
- data/lib/action_view/railtie.rb +0 -55
- data/lib/action_view/renderer/abstract_renderer.rb +0 -41
- data/lib/action_view/renderer/partial_renderer.rb +0 -415
- data/lib/action_view/renderer/renderer.rb +0 -54
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
- data/lib/action_view/renderer/template_renderer.rb +0 -94
- data/lib/action_view/template/error.rb +0 -128
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -125
- data/lib/action_view/template/handlers.rb +0 -50
- data/lib/action_view/template/resolver.rb +0 -272
- data/lib/action_view/template/text.rb +0 -30
- data/lib/action_view/template.rb +0 -337
- data/lib/action_view/test_case.rb +0 -245
- data/lib/action_view/testing/resolvers.rb +0 -50
- data/lib/action_view.rb +0 -84
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,77 +1,48 @@
|
|
1
1
|
require 'action_dispatch/http/request'
|
2
2
|
require 'action_dispatch/middleware/exception_wrapper'
|
3
|
-
require 'active_support/deprecation'
|
4
3
|
|
5
4
|
module ActionDispatch
|
6
5
|
# This middleware rescues any exception returned by the application
|
7
6
|
# and calls an exceptions app that will wrap it in a format for the end user.
|
8
7
|
#
|
9
8
|
# The exceptions app should be passed as parameter on initialization
|
10
|
-
# of ShowExceptions.
|
9
|
+
# of ShowExceptions. Every time there is an exception, ShowExceptions will
|
11
10
|
# store the exception in env["action_dispatch.exception"], rewrite the
|
12
11
|
# PATH_INFO to the exception status code and call the rack app.
|
13
|
-
#
|
12
|
+
#
|
14
13
|
# If the application returns a "X-Cascade" pass response, this middleware
|
15
14
|
# will send an empty response as result with the correct status code.
|
16
15
|
# If any exception happens inside the exceptions app, this middleware
|
17
16
|
# catches the exceptions and returns a FAILSAFE_RESPONSE.
|
18
17
|
class ShowExceptions
|
19
|
-
FAILSAFE_RESPONSE = [500, {'Content-Type' => 'text/
|
20
|
-
["
|
21
|
-
"If you are the administrator of this website, then please read this web "
|
22
|
-
"application's log file and/or the web server's log file to find out what "
|
23
|
-
"went wrong
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def rescue_responses
|
27
|
-
ActiveSupport::Deprecation.warn "ActionDispatch::ShowExceptions.rescue_responses is deprecated. " \
|
28
|
-
"Please configure your exceptions using a railtie or in your application config instead."
|
29
|
-
ExceptionWrapper.rescue_responses
|
30
|
-
end
|
31
|
-
|
32
|
-
def rescue_templates
|
33
|
-
ActiveSupport::Deprecation.warn "ActionDispatch::ShowExceptions.rescue_templates is deprecated. " \
|
34
|
-
"Please configure your exceptions using a railtie or in your application config instead."
|
35
|
-
ExceptionWrapper.rescue_templates
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def initialize(app, exceptions_app = nil)
|
40
|
-
if [true, false].include?(exceptions_app)
|
41
|
-
ActiveSupport::Deprecation.warn "Passing consider_all_requests_local option to ActionDispatch::ShowExceptions middleware no longer works"
|
42
|
-
exceptions_app = nil
|
43
|
-
end
|
44
|
-
|
45
|
-
if exceptions_app.nil?
|
46
|
-
raise ArgumentError, "You need to pass an exceptions_app when initializing ActionDispatch::ShowExceptions. " \
|
47
|
-
"In case you want to render pages from a public path, you can use ActionDispatch::PublicExceptions.new('path/to/public')"
|
48
|
-
end
|
18
|
+
FAILSAFE_RESPONSE = [500, { 'Content-Type' => 'text/plain' },
|
19
|
+
["500 Internal Server Error\n" \
|
20
|
+
"If you are the administrator of this website, then please read this web " \
|
21
|
+
"application's log file and/or the web server's log file to find out what " \
|
22
|
+
"went wrong."]]
|
49
23
|
|
24
|
+
def initialize(app, exceptions_app)
|
50
25
|
@app = app
|
51
26
|
@exceptions_app = exceptions_app
|
52
27
|
end
|
53
28
|
|
54
29
|
def call(env)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
raise exception
|
30
|
+
@app.call(env)
|
31
|
+
rescue Exception => exception
|
32
|
+
if env['action_dispatch.show_exceptions'] == false
|
33
|
+
raise exception
|
34
|
+
else
|
35
|
+
render_exception(env, exception)
|
59
36
|
end
|
60
|
-
|
61
|
-
response || render_exception(env, exception)
|
62
37
|
end
|
63
38
|
|
64
39
|
private
|
65
40
|
|
66
|
-
# Define this method because some plugins were monkey patching it.
|
67
|
-
# Remove this after 3.2 is out with the other deprecations in this class.
|
68
|
-
def status_code(*)
|
69
|
-
end
|
70
|
-
|
71
41
|
def render_exception(env, exception)
|
72
42
|
wrapper = ExceptionWrapper.new(env, exception)
|
73
43
|
status = wrapper.status_code
|
74
44
|
env["action_dispatch.exception"] = wrapper.exception
|
45
|
+
env["action_dispatch.original_path"] = env["PATH_INFO"]
|
75
46
|
env["PATH_INFO"] = "/#{status}"
|
76
47
|
response = @exceptions_app.call(env)
|
77
48
|
response[1]['X-Cascade'] == 'pass' ? pass_response(status) : response
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActionDispatch
|
2
|
+
class SSL
|
3
|
+
YEAR = 31536000
|
4
|
+
|
5
|
+
def self.default_hsts_options
|
6
|
+
{ :expires => YEAR, :subdomains => false }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(app, options = {})
|
10
|
+
@app = app
|
11
|
+
|
12
|
+
@hsts = options.fetch(:hsts, {})
|
13
|
+
@hsts = {} if @hsts == true
|
14
|
+
@hsts = self.class.default_hsts_options.merge(@hsts) if @hsts
|
15
|
+
|
16
|
+
@host = options[:host]
|
17
|
+
@port = options[:port]
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
request = Request.new(env)
|
22
|
+
|
23
|
+
if request.ssl?
|
24
|
+
status, headers, body = @app.call(env)
|
25
|
+
headers.reverse_merge!(hsts_headers)
|
26
|
+
flag_cookies_as_secure!(headers)
|
27
|
+
[status, headers, body]
|
28
|
+
else
|
29
|
+
redirect_to_https(request)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def redirect_to_https(request)
|
35
|
+
host = @host || request.host
|
36
|
+
port = @port || request.port
|
37
|
+
|
38
|
+
location = "https://#{host}"
|
39
|
+
location << ":#{port}" if port != 80
|
40
|
+
location << request.fullpath
|
41
|
+
|
42
|
+
headers = { 'Content-Type' => 'text/html', 'Location' => location }
|
43
|
+
|
44
|
+
[301, headers, []]
|
45
|
+
end
|
46
|
+
|
47
|
+
# http://tools.ietf.org/html/draft-hodges-strict-transport-sec-02
|
48
|
+
def hsts_headers
|
49
|
+
if @hsts
|
50
|
+
value = "max-age=#{@hsts[:expires].to_i}"
|
51
|
+
value += "; includeSubDomains" if @hsts[:subdomains]
|
52
|
+
{ 'Strict-Transport-Security' => value }
|
53
|
+
else
|
54
|
+
{}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def flag_cookies_as_secure!(headers)
|
59
|
+
if cookies = headers['Set-Cookie']
|
60
|
+
cookies = cookies.split("\n")
|
61
|
+
|
62
|
+
headers['Set-Cookie'] = cookies.map { |cookie|
|
63
|
+
if cookie !~ /;\s*secure\s*(;|$)/i
|
64
|
+
"#{cookie}; secure"
|
65
|
+
else
|
66
|
+
cookie
|
67
|
+
end
|
68
|
+
}.join("\n")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -75,6 +75,11 @@ module ActionDispatch
|
|
75
75
|
middlewares[i]
|
76
76
|
end
|
77
77
|
|
78
|
+
def unshift(*args, &block)
|
79
|
+
middleware = self.class::Middleware.new(*args, &block)
|
80
|
+
middlewares.unshift(middleware)
|
81
|
+
end
|
82
|
+
|
78
83
|
def initialize_copy(other)
|
79
84
|
self.middlewares = other.middlewares.dup
|
80
85
|
end
|
@@ -110,7 +115,7 @@ module ActionDispatch
|
|
110
115
|
def build(app = nil, &block)
|
111
116
|
app ||= block
|
112
117
|
raise "MiddlewareStack#build requires an app" unless app
|
113
|
-
middlewares.reverse.inject(app) { |a, e| e.build(a) }
|
118
|
+
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
|
114
119
|
end
|
115
120
|
|
116
121
|
protected
|
@@ -1,49 +1,106 @@
|
|
1
1
|
require 'rack/utils'
|
2
|
+
require 'active_support/core_ext/uri'
|
2
3
|
|
3
4
|
module ActionDispatch
|
5
|
+
# This middleware returns a file's contents from disk in the body response.
|
6
|
+
# When initialized it can accept an optional 'Cache-Control' header which
|
7
|
+
# will be set when a response containing a file's contents is delivered.
|
8
|
+
#
|
9
|
+
# This middleware will render the file specified in `env["PATH_INFO"]`
|
10
|
+
# where the base path is in the +root+ directory. For example if the +root+
|
11
|
+
# is set to `public/` then a request with `env["PATH_INFO"]` of
|
12
|
+
# `assets/application.js` will return a response with contents of a file
|
13
|
+
# located at `public/assets/application.js` if the file exists. If the file
|
14
|
+
# does not exist a 404 "File not Found" response will be returned.
|
4
15
|
class FileHandler
|
5
16
|
def initialize(root, cache_control)
|
6
17
|
@root = root.chomp('/')
|
7
18
|
@compiled_root = /^#{Regexp.escape(root)}/
|
8
|
-
headers
|
9
|
-
@file_server
|
19
|
+
headers = cache_control && { 'Cache-Control' => cache_control }
|
20
|
+
@file_server = ::Rack::File.new(@root, headers)
|
10
21
|
end
|
11
22
|
|
12
23
|
def match?(path)
|
13
|
-
path = path
|
24
|
+
path = URI.parser.unescape(path)
|
25
|
+
return false unless valid_path?(path)
|
14
26
|
|
15
|
-
|
16
|
-
|
27
|
+
paths = [path, "#{path}#{ext}", "#{path}/index#{ext}"].map { |v|
|
28
|
+
Rack::Utils.clean_path_info v
|
29
|
+
}
|
17
30
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
31
|
+
if match = paths.detect { |p|
|
32
|
+
path = File.join(@root, p.force_encoding('UTF-8'))
|
33
|
+
begin
|
34
|
+
File.file?(path) && File.readable?(path)
|
35
|
+
rescue SystemCallError
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
}
|
40
|
+
return ::Rack::Utils.escape(match)
|
23
41
|
end
|
24
42
|
end
|
25
43
|
|
26
44
|
def call(env)
|
27
|
-
|
28
|
-
|
45
|
+
path = env['PATH_INFO']
|
46
|
+
gzip_path = gzip_file_path(path)
|
29
47
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
48
|
+
if gzip_path && gzip_encoding_accepted?(env)
|
49
|
+
env['PATH_INFO'] = gzip_path
|
50
|
+
status, headers, body = @file_server.call(env)
|
51
|
+
if status == 304
|
52
|
+
return [status, headers, body]
|
53
|
+
end
|
54
|
+
headers['Content-Encoding'] = 'gzip'
|
55
|
+
headers['Content-Type'] = content_type(path)
|
56
|
+
else
|
57
|
+
status, headers, body = @file_server.call(env)
|
34
58
|
end
|
35
|
-
end
|
36
59
|
|
37
|
-
|
38
|
-
URI.parser.unescape(path)
|
39
|
-
end
|
60
|
+
headers['Vary'] = 'Accept-Encoding' if gzip_path
|
40
61
|
|
41
|
-
|
42
|
-
|
43
|
-
|
62
|
+
return [status, headers, body]
|
63
|
+
ensure
|
64
|
+
env['PATH_INFO'] = path
|
44
65
|
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def ext
|
69
|
+
::ActionController::Base.default_static_extension
|
70
|
+
end
|
71
|
+
|
72
|
+
def content_type(path)
|
73
|
+
::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
74
|
+
end
|
75
|
+
|
76
|
+
def gzip_encoding_accepted?(env)
|
77
|
+
env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/i
|
78
|
+
end
|
79
|
+
|
80
|
+
def gzip_file_path(path)
|
81
|
+
can_gzip_mime = content_type(path) =~ /\A(?:text\/|application\/javascript)/
|
82
|
+
gzip_path = "#{path}.gz"
|
83
|
+
if can_gzip_mime && File.exist?(File.join(@root, ::Rack::Utils.unescape(gzip_path)))
|
84
|
+
gzip_path
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def valid_path?(path)
|
91
|
+
path.valid_encoding? && !path.include?("\0")
|
92
|
+
end
|
45
93
|
end
|
46
94
|
|
95
|
+
# This middleware will attempt to return the contents of a file's body from
|
96
|
+
# disk in the response. If a file is not found on disk, the request will be
|
97
|
+
# delegated to the application stack. This middleware is commonly initialized
|
98
|
+
# to serve assets from a server's `public/` directory.
|
99
|
+
#
|
100
|
+
# This middleware verifies the path to ensure that only files
|
101
|
+
# living in the root directory can be rendered. A request cannot
|
102
|
+
# produce a directory traversal using this middleware. Only 'GET' and 'HEAD'
|
103
|
+
# requests will result in a file being returned.
|
47
104
|
class Static
|
48
105
|
def initialize(app, path, cache_control=nil)
|
49
106
|
@app = app
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<% unless @exception.blamed_files.blank? %>
|
2
|
+
<% if (hide = @exception.blamed_files.length > 8) %>
|
3
|
+
<a href="#" onclick="return toggleTrace()">Toggle blamed files</a>
|
4
|
+
<% end %>
|
5
|
+
<pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%
|
9
|
+
clean_params = @request.filtered_parameters.clone
|
10
|
+
clean_params.delete("action")
|
11
|
+
clean_params.delete("controller")
|
12
|
+
|
13
|
+
request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
|
14
|
+
|
15
|
+
def debug_hash(object)
|
16
|
+
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
17
|
+
end unless self.class.method_defined?(:debug_hash)
|
18
|
+
%>
|
19
|
+
|
20
|
+
<h2 style="margin-top: 30px">Request</h2>
|
21
|
+
<p><b>Parameters</b>:</p> <pre><%= request_dump %></pre>
|
22
|
+
|
23
|
+
<div class="details">
|
24
|
+
<div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
|
25
|
+
<div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<div class="details">
|
29
|
+
<div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div>
|
30
|
+
<div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<h2 style="margin-top: 30px">Response</h2>
|
34
|
+
<p><b>Headers</b>:</p> <pre><%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %></pre>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%
|
2
|
+
clean_params = @request.filtered_parameters.clone
|
3
|
+
clean_params.delete("action")
|
4
|
+
clean_params.delete("controller")
|
5
|
+
|
6
|
+
request_dump = clean_params.empty? ? 'None' : clean_params.inspect.gsub(',', ",\n")
|
7
|
+
|
8
|
+
def debug_hash(object)
|
9
|
+
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
10
|
+
end unless self.class.method_defined?(:debug_hash)
|
11
|
+
%>
|
12
|
+
|
13
|
+
Request parameters
|
14
|
+
<%= request_dump %>
|
15
|
+
|
16
|
+
Session dump
|
17
|
+
<%= debug_hash @request.session %>
|
18
|
+
|
19
|
+
Env dump
|
20
|
+
<%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %>
|
21
|
+
|
22
|
+
Response headers
|
23
|
+
<%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<% @source_extracts.each_with_index do |source_extract, index| %>
|
2
|
+
<% if source_extract[:code] %>
|
3
|
+
<div class="source <%="hidden" if @show_source_idx != index%>" id="frame-source-<%=index%>">
|
4
|
+
<div class="info">
|
5
|
+
Extracted source (around line <strong>#<%= source_extract[:line_number] %></strong>):
|
6
|
+
</div>
|
7
|
+
<div class="data">
|
8
|
+
<table cellpadding="0" cellspacing="0" class="lines">
|
9
|
+
<tr>
|
10
|
+
<td>
|
11
|
+
<pre class="line_numbers">
|
12
|
+
<% source_extract[:code].each_key do |line_number| %>
|
13
|
+
<span><%= line_number -%></span>
|
14
|
+
<% end %>
|
15
|
+
</pre>
|
16
|
+
</td>
|
17
|
+
<td width="100%">
|
18
|
+
<pre>
|
19
|
+
<% source_extract[:code].each do |line, source| -%><div class="line<%= " active" if line == source_extract[:line_number] -%>"><%= source -%></div><% end -%>
|
20
|
+
</pre>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
</table>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
<% end %>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
<% names = @traces.keys %>
|
2
|
+
|
3
|
+
<p><code>Rails.root: <%= defined?(Rails) && Rails.respond_to?(:root) ? Rails.root : "unset" %></code></p>
|
4
|
+
|
5
|
+
<div id="traces">
|
6
|
+
<% names.each do |name| %>
|
7
|
+
<%
|
8
|
+
show = "show('#{name.gsub(/\s/, '-')}');"
|
9
|
+
hide = (names - [name]).collect {|hide_name| "hide('#{hide_name.gsub(/\s/, '-')}');"}
|
10
|
+
%>
|
11
|
+
<a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% @traces.each do |name, trace| %>
|
15
|
+
<div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == @trace_to_show) ? 'block' : 'none' %>;">
|
16
|
+
<pre><code><% trace.each do |frame| %><a class="trace-frames" data-frame-id="<%= frame[:id] %>" href="#"><%= frame[:trace] %></a><br><% end %></code></pre>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<script type="text/javascript">
|
21
|
+
var traceFrames = document.getElementsByClassName('trace-frames');
|
22
|
+
var selectedFrame, currentSource = document.getElementById('frame-source-0');
|
23
|
+
|
24
|
+
// Add click listeners for all stack frames
|
25
|
+
for (var i = 0; i < traceFrames.length; i++) {
|
26
|
+
traceFrames[i].addEventListener('click', function(e) {
|
27
|
+
e.preventDefault();
|
28
|
+
var target = e.target;
|
29
|
+
var frame_id = target.dataset.frameId;
|
30
|
+
|
31
|
+
if (selectedFrame) {
|
32
|
+
selectedFrame.className = selectedFrame.className.replace("selected", "");
|
33
|
+
}
|
34
|
+
|
35
|
+
target.className += " selected";
|
36
|
+
selectedFrame = target;
|
37
|
+
|
38
|
+
// Change the extracted source code
|
39
|
+
changeSourceExtract(frame_id);
|
40
|
+
});
|
41
|
+
|
42
|
+
function changeSourceExtract(frame_id) {
|
43
|
+
var el = document.getElementById('frame-source-' + frame_id);
|
44
|
+
if (currentSource && el) {
|
45
|
+
currentSource.className += " hidden";
|
46
|
+
el.className = el.className.replace(" hidden", "");
|
47
|
+
currentSource = el;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
</script>
|
52
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>
|
3
|
+
<%= @exception.class.to_s %>
|
4
|
+
<% if @request.parameters['controller'] %>
|
5
|
+
in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
6
|
+
<% end %>
|
7
|
+
</h1>
|
8
|
+
</header>
|
9
|
+
|
10
|
+
<div id="container">
|
11
|
+
<h2><%= h @exception.message %></h2>
|
12
|
+
|
13
|
+
<%= render template: "rescues/_source" %>
|
14
|
+
<%= render template: "rescues/_trace" %>
|
15
|
+
<%= render template: "rescues/_request_and_response" %>
|
16
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%= @exception.class.to_s %><%
|
2
|
+
if @request.parameters['controller']
|
3
|
+
%> in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<%= @exception.message %>
|
7
|
+
<%= render template: "rescues/_source" %>
|
8
|
+
<%= render template: "rescues/_trace" %>
|
9
|
+
<%= render template: "rescues/_request_and_response" %>
|
@@ -4,7 +4,11 @@
|
|
4
4
|
<meta charset="utf-8" />
|
5
5
|
<title>Action Controller: Exception caught</title>
|
6
6
|
<style>
|
7
|
-
body {
|
7
|
+
body {
|
8
|
+
background-color: #FAFAFA;
|
9
|
+
color: #333;
|
10
|
+
margin: 0px;
|
11
|
+
}
|
8
12
|
|
9
13
|
body, p, ol, ul, td {
|
10
14
|
font-family: helvetica, verdana, arial, sans-serif;
|
@@ -13,16 +17,140 @@
|
|
13
17
|
}
|
14
18
|
|
15
19
|
pre {
|
16
|
-
background-color: #eee;
|
17
|
-
padding: 10px;
|
18
20
|
font-size: 11px;
|
19
21
|
white-space: pre-wrap;
|
20
22
|
}
|
21
23
|
|
22
|
-
|
24
|
+
pre.box {
|
25
|
+
border: 1px solid #EEE;
|
26
|
+
padding: 10px;
|
27
|
+
margin: 0px;
|
28
|
+
width: 958px;
|
29
|
+
}
|
30
|
+
|
31
|
+
header {
|
32
|
+
color: #F0F0F0;
|
33
|
+
background: #C52F24;
|
34
|
+
padding: 0.5em 1.5em;
|
35
|
+
}
|
36
|
+
|
37
|
+
h1 {
|
38
|
+
margin: 0.2em 0;
|
39
|
+
line-height: 1.1em;
|
40
|
+
font-size: 2em;
|
41
|
+
}
|
42
|
+
|
43
|
+
h2 {
|
44
|
+
color: #C52F24;
|
45
|
+
line-height: 25px;
|
46
|
+
}
|
47
|
+
|
48
|
+
.details {
|
49
|
+
border: 1px solid #D0D0D0;
|
50
|
+
border-radius: 4px;
|
51
|
+
margin: 1em 0px;
|
52
|
+
display: block;
|
53
|
+
width: 978px;
|
54
|
+
}
|
55
|
+
|
56
|
+
.summary {
|
57
|
+
padding: 8px 15px;
|
58
|
+
border-bottom: 1px solid #D0D0D0;
|
59
|
+
display: block;
|
60
|
+
}
|
61
|
+
|
62
|
+
.details pre {
|
63
|
+
margin: 5px;
|
64
|
+
border: none;
|
65
|
+
}
|
66
|
+
|
67
|
+
#container {
|
68
|
+
box-sizing: border-box;
|
69
|
+
width: 100%;
|
70
|
+
padding: 0 1.5em;
|
71
|
+
}
|
72
|
+
|
73
|
+
.source * {
|
74
|
+
margin: 0px;
|
75
|
+
padding: 0px;
|
76
|
+
}
|
77
|
+
|
78
|
+
.source {
|
79
|
+
border: 1px solid #D9D9D9;
|
80
|
+
background: #ECECEC;
|
81
|
+
width: 978px;
|
82
|
+
}
|
83
|
+
|
84
|
+
.source pre {
|
85
|
+
padding: 10px 0px;
|
86
|
+
border: none;
|
87
|
+
}
|
88
|
+
|
89
|
+
.source .data {
|
90
|
+
font-size: 80%;
|
91
|
+
overflow: auto;
|
92
|
+
background-color: #FFF;
|
93
|
+
}
|
94
|
+
|
95
|
+
.info {
|
96
|
+
padding: 0.5em;
|
97
|
+
}
|
98
|
+
|
99
|
+
.source .data .line_numbers {
|
100
|
+
background-color: #ECECEC;
|
101
|
+
color: #AAA;
|
102
|
+
padding: 1em .5em;
|
103
|
+
border-right: 1px solid #DDD;
|
104
|
+
text-align: right;
|
105
|
+
}
|
106
|
+
|
107
|
+
.line {
|
108
|
+
padding-left: 10px;
|
109
|
+
}
|
110
|
+
|
111
|
+
.line:hover {
|
112
|
+
background-color: #F6F6F6;
|
113
|
+
}
|
114
|
+
|
115
|
+
.line.active {
|
116
|
+
background-color: #FFCCCC;
|
117
|
+
}
|
118
|
+
|
119
|
+
.hidden {
|
120
|
+
display: none;
|
121
|
+
}
|
122
|
+
|
123
|
+
a { color: #980905; }
|
23
124
|
a:visited { color: #666; }
|
24
|
-
a
|
125
|
+
a.trace-frames { color: #666; }
|
126
|
+
a:hover { color: #C52F24; }
|
127
|
+
a.trace-frames.selected { color: #C52F24 }
|
128
|
+
|
129
|
+
<%= yield :style %>
|
25
130
|
</style>
|
131
|
+
|
132
|
+
<script>
|
133
|
+
var toggle = function(id) {
|
134
|
+
var s = document.getElementById(id).style;
|
135
|
+
s.display = s.display == 'none' ? 'block' : 'none';
|
136
|
+
return false;
|
137
|
+
}
|
138
|
+
var show = function(id) {
|
139
|
+
document.getElementById(id).style.display = 'block';
|
140
|
+
}
|
141
|
+
var hide = function(id) {
|
142
|
+
document.getElementById(id).style.display = 'none';
|
143
|
+
}
|
144
|
+
var toggleTrace = function() {
|
145
|
+
return toggle('blame_trace');
|
146
|
+
}
|
147
|
+
var toggleSessionDump = function() {
|
148
|
+
return toggle('session_dump');
|
149
|
+
}
|
150
|
+
var toggleEnvDump = function() {
|
151
|
+
return toggle('env_dump');
|
152
|
+
}
|
153
|
+
</script>
|
26
154
|
</head>
|
27
155
|
<body>
|
28
156
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<header>
|
2
|
+
<h1>Template is missing</h1>
|
3
|
+
</header>
|
4
|
+
|
5
|
+
<div id="container">
|
6
|
+
<h2><%= h @exception.message %></h2>
|
7
|
+
|
8
|
+
<%= render template: "rescues/_source" %>
|
9
|
+
<%= render template: "rescues/_trace" %>
|
10
|
+
<%= render template: "rescues/_request_and_response" %>
|
11
|
+
</div>
|