actionpack 4.2.10 → 7.2.0.rc1
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 +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,132 +1,145 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
2
6
|
|
3
7
|
module ActionDispatch
|
4
8
|
module Http
|
5
9
|
module MimeNegotiation
|
6
10
|
extend ActiveSupport::Concern
|
7
11
|
|
12
|
+
class InvalidType < ::Mime::Type::InvalidMimeType; end
|
13
|
+
|
14
|
+
RESCUABLE_MIME_FORMAT_ERRORS = [
|
15
|
+
ActionController::BadRequest,
|
16
|
+
ActionDispatch::Http::Parameters::ParseError,
|
17
|
+
]
|
18
|
+
|
8
19
|
included do
|
9
|
-
mattr_accessor :ignore_accept_header
|
10
|
-
self.ignore_accept_header = false
|
20
|
+
mattr_accessor :ignore_accept_header, default: false
|
11
21
|
end
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
# The MIME type of the HTTP request, such as Mime::XML.
|
16
|
-
#
|
17
|
-
# For backward compatibility, the post \format is extracted from the
|
18
|
-
# X-Post-Data-Format HTTP header if present.
|
23
|
+
# The MIME type of the HTTP request, such as [Mime](:xml).
|
19
24
|
def content_mime_type
|
20
|
-
|
21
|
-
if
|
25
|
+
fetch_header("action_dispatch.request.content_type") do |k|
|
26
|
+
v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
|
22
27
|
Mime::Type.lookup($1.strip.downcase)
|
23
28
|
else
|
24
29
|
nil
|
25
30
|
end
|
31
|
+
set_header k, v
|
32
|
+
rescue ::Mime::Type::InvalidMimeType => e
|
33
|
+
raise InvalidType, e.message
|
26
34
|
end
|
27
35
|
end
|
28
36
|
|
29
|
-
def
|
30
|
-
|
37
|
+
def has_content_type? # :nodoc:
|
38
|
+
get_header "CONTENT_TYPE"
|
31
39
|
end
|
32
40
|
|
33
41
|
# Returns the accepted MIME type for the request.
|
34
42
|
def accepts
|
35
|
-
|
36
|
-
header =
|
43
|
+
fetch_header("action_dispatch.request.accepts") do |k|
|
44
|
+
header = get_header("HTTP_ACCEPT").to_s.strip
|
37
45
|
|
38
|
-
if header.empty?
|
46
|
+
v = if header.empty?
|
39
47
|
[content_mime_type]
|
40
48
|
else
|
41
49
|
Mime::Type.parse(header)
|
42
50
|
end
|
51
|
+
set_header k, v
|
52
|
+
rescue ::Mime::Type::InvalidMimeType => e
|
53
|
+
raise InvalidType, e.message
|
43
54
|
end
|
44
55
|
end
|
45
56
|
|
46
|
-
# Returns the MIME type for the
|
57
|
+
# Returns the MIME type for the format used in the request.
|
47
58
|
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
59
|
+
# GET /posts/5.xml | request.format => Mime[:xml]
|
60
|
+
# GET /posts/5.xhtml | request.format => Mime[:html]
|
61
|
+
# GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
|
51
62
|
#
|
52
|
-
def format(
|
63
|
+
def format(_view_path = nil)
|
53
64
|
formats.first || Mime::NullType.instance
|
54
65
|
end
|
55
66
|
|
56
67
|
def formats
|
57
|
-
|
58
|
-
|
59
|
-
parameters[:format]
|
60
|
-
rescue ActionController::BadRequest
|
61
|
-
false
|
62
|
-
end
|
63
|
-
|
64
|
-
if params_readable
|
68
|
+
fetch_header("action_dispatch.request.formats") do |k|
|
69
|
+
v = if params_readable?
|
65
70
|
Array(Mime[parameters[:format]])
|
66
71
|
elsif use_accept_header && valid_accept_header
|
67
|
-
accepts
|
72
|
+
accepts.dup
|
73
|
+
elsif extension_format = format_from_path_extension
|
74
|
+
[extension_format]
|
68
75
|
elsif xhr?
|
69
|
-
[Mime
|
76
|
+
[Mime[:js]]
|
70
77
|
else
|
71
|
-
[Mime
|
78
|
+
[Mime[:html]]
|
72
79
|
end
|
80
|
+
|
81
|
+
v.select! do |format|
|
82
|
+
format.symbol || format.ref == "*/*"
|
83
|
+
end
|
84
|
+
|
85
|
+
set_header k, v
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
|
-
# Sets the
|
89
|
+
# Sets the variant for template.
|
77
90
|
def variant=(variant)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
@variant = variant
|
91
|
+
variant = Array(variant)
|
92
|
+
|
93
|
+
if variant.all?(Symbol)
|
94
|
+
@variant = ActiveSupport::ArrayInquirer.new(variant)
|
82
95
|
else
|
83
|
-
raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols
|
84
|
-
"For security reasons, never directly set the variant to a user-provided value, " \
|
85
|
-
"like params[:variant].to_sym. Check user-provided value against a whitelist first, " \
|
86
|
-
"then set the variant: request.variant = :tablet if params[:variant] == 'tablet'"
|
96
|
+
raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
|
87
97
|
end
|
88
98
|
end
|
89
99
|
|
90
|
-
|
100
|
+
def variant
|
101
|
+
@variant ||= ActiveSupport::ArrayInquirer.new
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets the format by string extension, which can be used to force custom formats
|
91
105
|
# that are not controlled by the extension.
|
92
106
|
#
|
93
|
-
#
|
94
|
-
#
|
107
|
+
# class ApplicationController < ActionController::Base
|
108
|
+
# before_action :adjust_format_for_iphone
|
95
109
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
110
|
+
# private
|
111
|
+
# def adjust_format_for_iphone
|
112
|
+
# request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
|
113
|
+
# end
|
114
|
+
# end
|
101
115
|
def format=(extension)
|
102
116
|
parameters[:format] = extension.to_s
|
103
|
-
|
117
|
+
set_header "action_dispatch.request.formats", [Mime::Type.lookup_by_extension(parameters[:format])]
|
104
118
|
end
|
105
119
|
|
106
|
-
# Sets the
|
107
|
-
# to set multiple, ordered formats, which is useful when you want to have a
|
120
|
+
# Sets the formats by string extensions. This differs from #format= by allowing
|
121
|
+
# you to set multiple, ordered formats, which is useful when you want to have a
|
122
|
+
# fallback.
|
108
123
|
#
|
109
|
-
# In this example, the
|
110
|
-
# to the
|
124
|
+
# In this example, the `:iphone` format will be used if it's available,
|
125
|
+
# otherwise it'll fall back to the `:html` format.
|
111
126
|
#
|
112
|
-
#
|
113
|
-
#
|
127
|
+
# class ApplicationController < ActionController::Base
|
128
|
+
# before_action :adjust_format_for_iphone_with_html_fallback
|
114
129
|
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
130
|
+
# private
|
131
|
+
# def adjust_format_for_iphone_with_html_fallback
|
132
|
+
# request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
|
133
|
+
# end
|
134
|
+
# end
|
120
135
|
def formats=(extensions)
|
121
136
|
parameters[:format] = extensions.first.to_s
|
122
|
-
|
137
|
+
set_header "action_dispatch.request.formats", extensions.collect { |extension|
|
123
138
|
Mime::Type.lookup_by_extension(extension)
|
124
|
-
|
139
|
+
}
|
125
140
|
end
|
126
141
|
|
127
|
-
#
|
128
|
-
# matches the order array.
|
129
|
-
#
|
142
|
+
# Returns the first MIME type that matches the provided array of MIME types.
|
130
143
|
def negotiate_mime(order)
|
131
144
|
formats.each do |priority|
|
132
145
|
if priority == Mime::ALL
|
@@ -139,18 +152,36 @@ module ActionDispatch
|
|
139
152
|
order.include?(Mime::ALL) ? format : nil
|
140
153
|
end
|
141
154
|
|
142
|
-
|
155
|
+
def should_apply_vary_header?
|
156
|
+
!params_readable? && use_accept_header && valid_accept_header
|
157
|
+
end
|
143
158
|
|
144
|
-
|
159
|
+
private
|
160
|
+
# We use normal content negotiation unless you include **/** in your list, in
|
161
|
+
# which case we assume you're a browser and send HTML.
|
162
|
+
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
|
145
163
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
164
|
+
def params_readable?
|
165
|
+
parameters[:format]
|
166
|
+
rescue *RESCUABLE_MIME_FORMAT_ERRORS
|
167
|
+
false
|
168
|
+
end
|
150
169
|
|
151
|
-
|
152
|
-
|
153
|
-
|
170
|
+
def valid_accept_header
|
171
|
+
(xhr? && (accept.present? || content_mime_type)) ||
|
172
|
+
(accept.present? && !accept.match?(BROWSER_LIKE_ACCEPTS))
|
173
|
+
end
|
174
|
+
|
175
|
+
def use_accept_header
|
176
|
+
!self.class.ignore_accept_header
|
177
|
+
end
|
178
|
+
|
179
|
+
def format_from_path_extension
|
180
|
+
path = get_header("action_dispatch.original_path") || get_header("PATH_INFO")
|
181
|
+
if match = path && path.match(/\.(\w+)\z/)
|
182
|
+
Mime[match.captures.first]
|
183
|
+
end
|
184
|
+
end
|
154
185
|
end
|
155
186
|
end
|
156
187
|
end
|