actionpack 4.2.11.1 → 6.1.3.2
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 +4 -4
- data/CHANGELOG.md +291 -489
- data/MIT-LICENSE +1 -1
- data/README.rdoc +9 -9
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +81 -51
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +64 -17
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/callbacks.rb +61 -33
- data/lib/abstract_controller/collector.rb +9 -13
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +115 -99
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +21 -3
- data/lib/abstract_controller/rendering.rb +48 -47
- data/lib/abstract_controller/translation.rb +17 -8
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/abstract_controller.rb +13 -5
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/api.rb +150 -0
- data/lib/action_controller/base.rb +29 -24
- data/lib/action_controller/caching.rb +12 -57
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +17 -19
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +134 -46
- data/lib/action_controller/metal/content_security_policy.rb +51 -0
- data/lib/action_controller/metal/cookies.rb +6 -4
- data/lib/action_controller/metal/data_streaming.rb +30 -50
- data/lib/action_controller/metal/default_headers.rb +17 -0
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +21 -16
- data/lib/action_controller/metal/exceptions.rb +63 -15
- data/lib/action_controller/metal/flash.rb +9 -8
- data/lib/action_controller/metal/head.rb +26 -21
- data/lib/action_controller/metal/helpers.rb +37 -18
- data/lib/action_controller/metal/http_authentication.rb +81 -73
- data/lib/action_controller/metal/implicit_render.rb +53 -9
- data/lib/action_controller/metal/instrumentation.rb +32 -35
- data/lib/action_controller/metal/live.rb +102 -120
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +49 -47
- data/lib/action_controller/metal/parameter_encoding.rb +82 -0
- data/lib/action_controller/metal/params_wrapper.rb +83 -66
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +53 -32
- data/lib/action_controller/metal/renderers.rb +87 -44
- data/lib/action_controller/metal/rendering.rb +77 -50
- data/lib/action_controller/metal/request_forgery_protection.rb +267 -103
- data/lib/action_controller/metal/rescue.rb +10 -17
- data/lib/action_controller/metal/streaming.rb +12 -11
- data/lib/action_controller/metal/strong_parameters.rb +714 -186
- data/lib/action_controller/metal/testing.rb +2 -17
- data/lib/action_controller/metal/url_for.rb +19 -10
- data/lib/action_controller/metal.rb +104 -87
- data/lib/action_controller/railtie.rb +28 -10
- data/lib/action_controller/railties/helpers.rb +3 -1
- data/lib/action_controller/renderer.rb +141 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +296 -422
- data/lib/action_controller.rb +34 -23
- data/lib/action_dispatch/http/cache.rb +107 -56
- data/lib/action_dispatch/http/content_disposition.rb +45 -0
- data/lib/action_dispatch/http/content_security_policy.rb +286 -0
- data/lib/action_dispatch/http/filter_parameters.rb +32 -25
- data/lib/action_dispatch/http/filter_redirect.rb +10 -12
- data/lib/action_dispatch/http/headers.rb +55 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +79 -51
- data/lib/action_dispatch/http/mime_type.rb +153 -121
- data/lib/action_dispatch/http/mime_types.rb +20 -6
- data/lib/action_dispatch/http/parameters.rb +90 -40
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +226 -121
- data/lib/action_dispatch/http/response.rb +248 -113
- data/lib/action_dispatch/http/upload.rb +21 -7
- data/lib/action_dispatch/http/url.rb +182 -100
- data/lib/action_dispatch/journey/formatter.rb +90 -43
- data/lib/action_dispatch/journey/gtg/builder.rb +28 -41
- data/lib/action_dispatch/journey/gtg/simulator.rb +11 -16
- data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -21
- data/lib/action_dispatch/journey/nfa/dot.rb +3 -14
- data/lib/action_dispatch/journey/nodes/node.rb +29 -15
- data/lib/action_dispatch/journey/parser.rb +17 -16
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +12 -4
- data/lib/action_dispatch/journey/path/pattern.rb +58 -54
- data/lib/action_dispatch/journey/route.rb +100 -32
- data/lib/action_dispatch/journey/router/utils.rb +29 -18
- data/lib/action_dispatch/journey/router.rb +55 -51
- data/lib/action_dispatch/journey/routes.rb +17 -17
- data/lib/action_dispatch/journey/scanner.rb +26 -17
- data/lib/action_dispatch/journey/visitors.rb +98 -54
- data/lib/action_dispatch/journey.rb +5 -5
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/callbacks.rb +3 -6
- data/lib/action_dispatch/middleware/cookies.rb +347 -217
- data/lib/action_dispatch/middleware/debug_exceptions.rb +135 -63
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/debug_view.rb +66 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +115 -71
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +78 -54
- data/lib/action_dispatch/middleware/host_authorization.rb +130 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
- data/lib/action_dispatch/middleware/reloader.rb +5 -91
- data/lib/action_dispatch/middleware/remote_ip.rb +53 -45
- data/lib/action_dispatch/middleware/request_id.rb +17 -10
- data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
- data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
- data/lib/action_dispatch/middleware/session/cookie_store.rb +74 -75
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +28 -23
- data/lib/action_dispatch/middleware/ssl.rb +118 -35
- data/lib/action_dispatch/middleware/stack.rb +82 -41
- data/lib/action_dispatch/middleware/static.rb +156 -89
- 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 +4 -14
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +105 -8
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -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 +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +87 -64
- data/lib/action_dispatch/railtie.rb +27 -13
- data/lib/action_dispatch/request/session.rb +109 -61
- data/lib/action_dispatch/request/utils.rb +90 -23
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +141 -102
- data/lib/action_dispatch/routing/mapper.rb +811 -473
- data/lib/action_dispatch/routing/polymorphic_routes.rb +167 -143
- data/lib/action_dispatch/routing/redirection.rb +37 -27
- data/lib/action_dispatch/routing/route_set.rb +363 -331
- data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
- data/lib/action_dispatch/routing/url_for.rb +66 -26
- data/lib/action_dispatch/routing.rb +36 -36
- data/lib/action_dispatch/system_test_case.rb +190 -0
- data/lib/action_dispatch/system_testing/browser.rb +86 -0
- data/lib/action_dispatch/system_testing/driver.rb +67 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +138 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +29 -0
- data/lib/action_dispatch/testing/assertion_response.rb +46 -0
- data/lib/action_dispatch/testing/assertions/response.rb +44 -22
- data/lib/action_dispatch/testing/assertions/routing.rb +47 -31
- data/lib/action_dispatch/testing/assertions.rb +6 -4
- data/lib/action_dispatch/testing/integration.rb +391 -220
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +53 -22
- data/lib/action_dispatch/testing/test_request.rb +27 -34
- data/lib/action_dispatch/testing/test_response.rb +11 -11
- data/lib/action_dispatch.rb +35 -21
- data/lib/action_pack/gem_version.rb +6 -4
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +4 -2
- metadata +78 -48
- 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/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,23 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "singleton"
|
4
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
5
5
|
|
6
6
|
module Mime
|
7
|
-
class Mimes
|
8
|
-
|
9
|
-
|
7
|
+
class Mimes
|
8
|
+
attr_reader :symbols
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@mimes = []
|
14
|
+
@symbols = []
|
10
15
|
end
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
def each
|
18
|
+
@mimes.each { |x| yield x }
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(type)
|
22
|
+
@mimes << type
|
23
|
+
@symbols << type.to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete_if
|
27
|
+
@mimes.delete_if do |x|
|
28
|
+
if yield x
|
29
|
+
@symbols.delete(x.to_sym)
|
30
|
+
true
|
19
31
|
end
|
20
|
-
|
32
|
+
end
|
21
33
|
end
|
22
34
|
end
|
23
35
|
|
@@ -37,7 +49,7 @@ module Mime
|
|
37
49
|
end
|
38
50
|
end
|
39
51
|
|
40
|
-
# Encapsulates the notion of a
|
52
|
+
# Encapsulates the notion of a MIME type. Can be used at render time, for example, with:
|
41
53
|
#
|
42
54
|
# class PostsController < ActionController::Base
|
43
55
|
# def show
|
@@ -45,20 +57,17 @@ module Mime
|
|
45
57
|
#
|
46
58
|
# respond_to do |format|
|
47
59
|
# format.html
|
48
|
-
# format.ics { render
|
60
|
+
# format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
|
49
61
|
# format.xml { render xml: @post }
|
50
62
|
# end
|
51
63
|
# end
|
52
64
|
# end
|
53
65
|
class Type
|
54
|
-
@@html_types = Set.new [:html, :all]
|
55
|
-
cattr_reader :html_types
|
56
|
-
|
57
66
|
attr_reader :symbol
|
58
67
|
|
59
68
|
@register_callbacks = []
|
60
69
|
|
61
|
-
# A simple helper class used in parsing the accept header
|
70
|
+
# A simple helper class used in parsing the accept header.
|
62
71
|
class AcceptItem #:nodoc:
|
63
72
|
attr_accessor :index, :name, :q
|
64
73
|
alias :to_s :name
|
@@ -66,7 +75,7 @@ module Mime
|
|
66
75
|
def initialize(index, name, q = nil)
|
67
76
|
@index = index
|
68
77
|
@name = name
|
69
|
-
q ||= 0.0 if @name ==
|
78
|
+
q ||= 0.0 if @name == "*/*" # Default wildcard match to end of list.
|
70
79
|
@q = ((q || 1.0).to_f * 100).to_i
|
71
80
|
end
|
72
81
|
|
@@ -75,70 +84,58 @@ module Mime
|
|
75
84
|
result = @index <=> item.index if result == 0
|
76
85
|
result
|
77
86
|
end
|
78
|
-
|
79
|
-
def ==(item)
|
80
|
-
@name == item.to_s
|
81
|
-
end
|
82
87
|
end
|
83
88
|
|
84
|
-
class AcceptList
|
85
|
-
def
|
86
|
-
sort!
|
89
|
+
class AcceptList #:nodoc:
|
90
|
+
def self.sort!(list)
|
91
|
+
list.sort!
|
87
92
|
|
88
|
-
|
93
|
+
text_xml_idx = find_item_by_name list, "text/xml"
|
94
|
+
app_xml_idx = find_item_by_name list, Mime[:xml].to_s
|
95
|
+
|
96
|
+
# Take care of the broken text/xml entry by renaming or deleting it.
|
89
97
|
if text_xml_idx && app_xml_idx
|
90
|
-
app_xml
|
91
|
-
|
92
|
-
|
98
|
+
app_xml = list[app_xml_idx]
|
99
|
+
text_xml = list[text_xml_idx]
|
100
|
+
|
101
|
+
app_xml.q = [text_xml.q, app_xml.q].max # Set the q value to the max of the two.
|
102
|
+
if app_xml_idx > text_xml_idx # Make sure app_xml is ahead of text_xml in the list.
|
103
|
+
list[app_xml_idx], list[text_xml_idx] = text_xml, app_xml
|
104
|
+
app_xml_idx, text_xml_idx = text_xml_idx, app_xml_idx
|
105
|
+
end
|
106
|
+
list.delete_at(text_xml_idx) # Delete text_xml from the list.
|
93
107
|
elsif text_xml_idx
|
94
|
-
|
108
|
+
list[text_xml_idx].name = Mime[:xml].to_s
|
95
109
|
end
|
96
110
|
|
97
|
-
# Look for more specific XML-based types and sort them ahead of app/xml
|
111
|
+
# Look for more specific XML-based types and sort them ahead of app/xml.
|
98
112
|
if app_xml_idx
|
113
|
+
app_xml = list[app_xml_idx]
|
99
114
|
idx = app_xml_idx
|
100
115
|
|
101
|
-
while idx < length
|
102
|
-
type =
|
116
|
+
while idx < list.length
|
117
|
+
type = list[idx]
|
103
118
|
break if type.q < app_xml.q
|
104
119
|
|
105
|
-
if type.name.
|
106
|
-
|
107
|
-
|
120
|
+
if type.name.end_with? "+xml"
|
121
|
+
list[app_xml_idx], list[idx] = list[idx], app_xml
|
122
|
+
app_xml_idx = idx
|
108
123
|
end
|
109
124
|
idx += 1
|
110
125
|
end
|
111
126
|
end
|
112
127
|
|
113
|
-
map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
114
|
-
|
128
|
+
list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
129
|
+
list
|
115
130
|
end
|
116
131
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
def app_xml_idx
|
123
|
-
@app_xml_idx ||= index(Mime::XML.to_s)
|
124
|
-
end
|
125
|
-
|
126
|
-
def text_xml
|
127
|
-
self[text_xml_idx]
|
128
|
-
end
|
129
|
-
|
130
|
-
def app_xml
|
131
|
-
self[app_xml_idx]
|
132
|
-
end
|
133
|
-
|
134
|
-
def exchange_xml_items
|
135
|
-
self[app_xml_idx], self[text_xml_idx] = text_xml, app_xml
|
136
|
-
@app_xml_idx, @text_xml_idx = text_xml_idx, app_xml_idx
|
137
|
-
end
|
132
|
+
def self.find_item_by_name(array, name)
|
133
|
+
array.index { |item| item.name == name }
|
134
|
+
end
|
138
135
|
end
|
139
136
|
|
140
137
|
class << self
|
141
|
-
TRAILING_STAR_REGEXP =
|
138
|
+
TRAILING_STAR_REGEXP = /^(text|application)\/\*/
|
142
139
|
PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/
|
143
140
|
|
144
141
|
def register_callback(&block)
|
@@ -153,46 +150,48 @@ module Mime
|
|
153
150
|
EXTENSION_LOOKUP[extension.to_s]
|
154
151
|
end
|
155
152
|
|
156
|
-
# Registers an alias that's not used on
|
153
|
+
# Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for
|
157
154
|
# rendering different HTML versions depending on the user agent, like an iPhone.
|
158
155
|
def register_alias(string, symbol, extension_synonyms = [])
|
159
156
|
register(string, symbol, [], extension_synonyms, true)
|
160
157
|
end
|
161
158
|
|
162
159
|
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
163
|
-
|
160
|
+
new_mime = Type.new(string, symbol, mime_type_synonyms)
|
164
161
|
|
165
|
-
new_mime = Mime.const_get(symbol.upcase)
|
166
162
|
SET << new_mime
|
167
163
|
|
168
|
-
([string] + mime_type_synonyms).each { |str| LOOKUP[str] =
|
169
|
-
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] =
|
164
|
+
([string] + mime_type_synonyms).each { |str| LOOKUP[str] = new_mime } unless skip_lookup
|
165
|
+
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = new_mime }
|
170
166
|
|
171
167
|
@register_callbacks.each do |callback|
|
172
168
|
callback.call(new_mime)
|
173
169
|
end
|
170
|
+
new_mime
|
174
171
|
end
|
175
172
|
|
176
173
|
def parse(accept_header)
|
177
|
-
if !accept_header.include?(
|
174
|
+
if !accept_header.include?(",")
|
178
175
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
176
|
+
return [] unless accept_header
|
179
177
|
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
180
178
|
else
|
181
|
-
list, index =
|
182
|
-
accept_header.split(
|
179
|
+
list, index = [], 0
|
180
|
+
accept_header.split(",").each do |header|
|
183
181
|
params, q = header.split(PARAMETER_SEPARATOR_REGEXP)
|
184
|
-
if params.present?
|
185
|
-
params.strip!
|
186
182
|
|
187
|
-
|
183
|
+
next unless params
|
184
|
+
params.strip!
|
185
|
+
next if params.empty?
|
186
|
+
|
187
|
+
params = parse_trailing_star(params) || [params]
|
188
188
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
189
|
+
params.each do |m|
|
190
|
+
list << AcceptItem.new(index, m.to_s, q)
|
191
|
+
index += 1
|
193
192
|
end
|
194
193
|
end
|
195
|
-
|
194
|
+
AcceptList.sort! list
|
196
195
|
end
|
197
196
|
end
|
198
197
|
|
@@ -200,34 +199,44 @@ module Mime
|
|
200
199
|
parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
|
201
200
|
end
|
202
201
|
|
203
|
-
# For an input of <tt>'text'</tt>, returns <tt>[Mime
|
204
|
-
# Mime
|
202
|
+
# For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics],
|
203
|
+
# Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]</tt>.
|
205
204
|
#
|
206
|
-
# For an input of <tt>'application'</tt>, returns <tt>[Mime
|
207
|
-
# Mime
|
208
|
-
def parse_data_with_trailing_star(
|
209
|
-
Mime::SET.select { |m| m
|
205
|
+
# For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
|
206
|
+
# Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>.
|
207
|
+
def parse_data_with_trailing_star(type)
|
208
|
+
Mime::SET.select { |m| m.match?(type) }
|
210
209
|
end
|
211
210
|
|
212
211
|
# This method is opposite of register method.
|
213
212
|
#
|
214
|
-
#
|
213
|
+
# To unregister a MIME type:
|
215
214
|
#
|
216
215
|
# Mime::Type.unregister(:mobile)
|
217
216
|
def unregister(symbol)
|
218
|
-
symbol = symbol.
|
219
|
-
mime = Mime
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
|
217
|
+
symbol = symbol.downcase
|
218
|
+
if mime = Mime[symbol]
|
219
|
+
SET.delete_if { |v| v.eql?(mime) }
|
220
|
+
LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
221
|
+
EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
222
|
+
end
|
225
223
|
end
|
226
224
|
end
|
227
225
|
|
228
226
|
attr_reader :hash
|
229
227
|
|
228
|
+
MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
229
|
+
MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
230
|
+
MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
|
231
|
+
MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
|
232
|
+
MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/
|
233
|
+
|
234
|
+
class InvalidMimeType < StandardError; end
|
235
|
+
|
230
236
|
def initialize(string, symbol = nil, synonyms = [])
|
237
|
+
unless MIME_REGEXP.match?(string)
|
238
|
+
raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
|
239
|
+
end
|
231
240
|
@symbol, @synonyms = symbol, synonyms
|
232
241
|
@string = string
|
233
242
|
@hash = [@string, @synonyms, @symbol].hash
|
@@ -246,7 +255,7 @@ module Mime
|
|
246
255
|
end
|
247
256
|
|
248
257
|
def ref
|
249
|
-
|
258
|
+
symbol || to_s
|
250
259
|
end
|
251
260
|
|
252
261
|
def ===(list)
|
@@ -258,7 +267,7 @@ module Mime
|
|
258
267
|
end
|
259
268
|
|
260
269
|
def ==(mime_type)
|
261
|
-
return false
|
270
|
+
return false unless mime_type
|
262
271
|
(@synonyms + [ self ]).any? do |synonym|
|
263
272
|
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
|
264
273
|
end
|
@@ -272,40 +281,59 @@ module Mime
|
|
272
281
|
end
|
273
282
|
|
274
283
|
def =~(mime_type)
|
275
|
-
return false
|
284
|
+
return false unless mime_type
|
276
285
|
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
277
|
-
|
278
|
-
|
279
|
-
|
286
|
+
@synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
|
287
|
+
end
|
288
|
+
|
289
|
+
def match?(mime_type)
|
290
|
+
return false unless mime_type
|
291
|
+
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
292
|
+
@synonyms.any? { |synonym| synonym.to_s.match?(regexp) } || @string.match?(regexp)
|
280
293
|
end
|
281
294
|
|
282
295
|
def html?
|
283
|
-
|
296
|
+
(symbol == :html) || /html/.match?(@string)
|
284
297
|
end
|
285
298
|
|
299
|
+
def all?; false; end
|
286
300
|
|
287
301
|
protected
|
288
|
-
|
289
|
-
attr_reader :string, :synonyms
|
302
|
+
attr_reader :string, :synonyms
|
290
303
|
|
291
304
|
private
|
305
|
+
def to_ary; end
|
306
|
+
def to_a; end
|
292
307
|
|
293
|
-
|
294
|
-
|
308
|
+
def method_missing(method, *args)
|
309
|
+
if method.end_with?("?")
|
310
|
+
method[0..-2].downcase.to_sym == to_sym
|
311
|
+
else
|
312
|
+
super
|
313
|
+
end
|
314
|
+
end
|
295
315
|
|
296
|
-
|
297
|
-
|
298
|
-
method[0..-2].downcase.to_sym == to_sym
|
299
|
-
else
|
300
|
-
super
|
316
|
+
def respond_to_missing?(method, include_private = false)
|
317
|
+
method.end_with?("?") || super
|
301
318
|
end
|
302
|
-
|
319
|
+
end
|
320
|
+
|
321
|
+
class AllType < Type
|
322
|
+
include Singleton
|
303
323
|
|
304
|
-
def
|
305
|
-
|
324
|
+
def initialize
|
325
|
+
super "*/*", nil
|
306
326
|
end
|
327
|
+
|
328
|
+
def all?; true; end
|
329
|
+
def html?; true; end
|
307
330
|
end
|
308
331
|
|
332
|
+
# ALL isn't a real MIME type, so we don't register it for lookup with the
|
333
|
+
# other concrete types. It's a wildcard match that we use for +respond_to+
|
334
|
+
# negotiation internals.
|
335
|
+
ALL = AllType.instance
|
336
|
+
|
309
337
|
class NullType
|
310
338
|
include Singleton
|
311
339
|
|
@@ -313,17 +341,21 @@ module Mime
|
|
313
341
|
true
|
314
342
|
end
|
315
343
|
|
316
|
-
def
|
317
|
-
|
318
|
-
def respond_to_missing?(method, include_private = false)
|
319
|
-
method.to_s.ends_with? '?'
|
344
|
+
def to_s
|
345
|
+
""
|
320
346
|
end
|
321
347
|
|
348
|
+
def ref; end
|
349
|
+
|
322
350
|
private
|
323
|
-
|
324
|
-
|
325
|
-
|
351
|
+
def respond_to_missing?(method, _)
|
352
|
+
method.end_with?("?")
|
353
|
+
end
|
354
|
+
|
355
|
+
def method_missing(method, *args)
|
356
|
+
false if method.end_with?("?")
|
357
|
+
end
|
326
358
|
end
|
327
359
|
end
|
328
360
|
|
329
|
-
require
|
361
|
+
require "action_dispatch/http/mime_types"
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Build list of Mime types for HTTP responses
|
2
|
-
#
|
4
|
+
# https://www.iana.org/assignments/media-types/
|
3
5
|
|
4
6
|
Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
|
5
7
|
Mime::Type.register "text/plain", :text, [], %w(txt)
|
@@ -8,29 +10,41 @@ Mime::Type.register "text/css", :css
|
|
8
10
|
Mime::Type.register "text/calendar", :ics
|
9
11
|
Mime::Type.register "text/csv", :csv
|
10
12
|
Mime::Type.register "text/vcard", :vcf
|
13
|
+
Mime::Type.register "text/vtt", :vtt, %w(vtt)
|
11
14
|
|
12
15
|
Mime::Type.register "image/png", :png, [], %w(png)
|
13
16
|
Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe pjpeg)
|
14
17
|
Mime::Type.register "image/gif", :gif, [], %w(gif)
|
15
18
|
Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
|
16
19
|
Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
|
20
|
+
Mime::Type.register "image/svg+xml", :svg
|
17
21
|
|
18
22
|
Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe)
|
19
23
|
|
24
|
+
Mime::Type.register "audio/mpeg", :mp3, [], %w(mp1 mp2 mp3)
|
25
|
+
Mime::Type.register "audio/ogg", :ogg, [], %w(oga ogg spx opus)
|
26
|
+
Mime::Type.register "audio/aac", :m4a, %w( audio/mp4 ), %w(m4a mpg4 aac)
|
27
|
+
|
28
|
+
Mime::Type.register "video/webm", :webm, [], %w(webm)
|
29
|
+
Mime::Type.register "video/mp4", :mp4, [], %w(mp4 m4v)
|
30
|
+
|
31
|
+
Mime::Type.register "font/otf", :otf, [], %w(otf)
|
32
|
+
Mime::Type.register "font/ttf", :ttf, [], %w(ttf)
|
33
|
+
Mime::Type.register "font/woff", :woff, [], %w(woff)
|
34
|
+
Mime::Type.register "font/woff2", :woff2, [], %w(woff2)
|
35
|
+
|
20
36
|
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
|
21
37
|
Mime::Type.register "application/rss+xml", :rss
|
22
38
|
Mime::Type.register "application/atom+xml", :atom
|
23
|
-
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
|
39
|
+
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml ), %w(yml yaml)
|
24
40
|
|
25
41
|
Mime::Type.register "multipart/form-data", :multipart_form
|
26
42
|
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
|
27
43
|
|
28
|
-
#
|
44
|
+
# https://www.ietf.org/rfc/rfc4627.txt
|
29
45
|
# http://www.json.org/JSONRequest.html
|
30
46
|
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
|
31
47
|
|
32
48
|
Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
|
33
49
|
Mime::Type.register "application/zip", :zip, [], %w(zip)
|
34
|
-
|
35
|
-
# Create Mime::ALL but do not add it to the SET.
|
36
|
-
Mime::ALL = Mime::Type.new("*/*", :all, [])
|
50
|
+
Mime::Type.register "application/gzip", :gzip, %w(application/x-gzip), %w(gz)
|
@@ -1,35 +1,78 @@
|
|
1
|
-
|
2
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
-
require 'active_support/deprecation'
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
3
|
module ActionDispatch
|
6
4
|
module Http
|
7
5
|
module Parameters
|
8
|
-
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
PARAMETERS_KEY = "action_dispatch.request.path_parameters"
|
9
|
+
|
10
|
+
DEFAULT_PARSERS = {
|
11
|
+
Mime[:json].symbol => -> (raw_post) {
|
12
|
+
data = ActiveSupport::JSON.decode(raw_post)
|
13
|
+
data.is_a?(Hash) ? data : { _json: data }
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
# Raised when raw data from the request cannot be parsed by the parser
|
18
|
+
# defined for request's content MIME type.
|
19
|
+
class ParseError < StandardError
|
20
|
+
def initialize
|
21
|
+
super($!.message)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
included do
|
26
|
+
class << self
|
27
|
+
# Returns the parameter parsers.
|
28
|
+
attr_reader :parameter_parsers
|
29
|
+
end
|
30
|
+
|
31
|
+
self.parameter_parsers = DEFAULT_PARSERS
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
# Configure the parameter parser for a given MIME type.
|
36
|
+
#
|
37
|
+
# It accepts a hash where the key is the symbol of the MIME type
|
38
|
+
# and the value is a proc.
|
39
|
+
#
|
40
|
+
# original_parsers = ActionDispatch::Request.parameter_parsers
|
41
|
+
# xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
|
42
|
+
# new_parsers = original_parsers.merge(xml: xml_parser)
|
43
|
+
# ActionDispatch::Request.parameter_parsers = new_parsers
|
44
|
+
def parameter_parsers=(parsers)
|
45
|
+
@parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
|
46
|
+
end
|
47
|
+
end
|
9
48
|
|
10
49
|
# Returns both GET and POST \parameters in a single hash.
|
11
50
|
def parameters
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
51
|
+
params = get_header("action_dispatch.request.parameters")
|
52
|
+
return params if params
|
53
|
+
|
54
|
+
params = begin
|
55
|
+
request_parameters.merge(query_parameters)
|
56
|
+
rescue EOFError
|
57
|
+
query_parameters.dup
|
58
|
+
end
|
59
|
+
params.merge!(path_parameters)
|
60
|
+
set_header("action_dispatch.request.parameters", params)
|
61
|
+
params
|
20
62
|
end
|
21
63
|
alias :params :parameters
|
22
64
|
|
23
65
|
def path_parameters=(parameters) #:nodoc:
|
24
|
-
|
25
|
-
|
26
|
-
|
66
|
+
delete_header("action_dispatch.request.parameters")
|
67
|
+
|
68
|
+
parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
|
69
|
+
# If any of the path parameters has an invalid encoding then
|
70
|
+
# raise since it's likely to trigger errors further on.
|
71
|
+
Request::Utils.check_param_encoding(parameters)
|
27
72
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
)
|
32
|
-
path_parameters
|
73
|
+
set_header PARAMETERS_KEY, parameters
|
74
|
+
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
|
75
|
+
raise ActionController::BadRequest.new("Invalid path parameters: #{e.message}")
|
33
76
|
end
|
34
77
|
|
35
78
|
# Returns a hash with the \parameters used to form the \path of the request.
|
@@ -37,31 +80,38 @@ module ActionDispatch
|
|
37
80
|
#
|
38
81
|
# {'action' => 'my_action', 'controller' => 'my_controller'}
|
39
82
|
def path_parameters
|
40
|
-
|
83
|
+
get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
|
41
84
|
end
|
42
85
|
|
43
|
-
|
86
|
+
private
|
87
|
+
def parse_formatted_parameters(parsers)
|
88
|
+
return yield if content_length.zero? || content_mime_type.nil?
|
44
89
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
else
|
53
|
-
params.each_with_object({}) do |(key, val), new_hash|
|
54
|
-
new_hash[key] = if val.is_a?(Array)
|
55
|
-
val.map! { |el| normalize_encode_params(el) }
|
56
|
-
else
|
57
|
-
normalize_encode_params(val)
|
58
|
-
end
|
59
|
-
end.with_indifferent_access
|
90
|
+
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
|
91
|
+
|
92
|
+
begin
|
93
|
+
strategy.call(raw_post)
|
94
|
+
rescue # JSON or Ruby code block errors.
|
95
|
+
log_parse_error_once
|
96
|
+
raise ParseError
|
60
97
|
end
|
61
|
-
else
|
62
|
-
params
|
63
98
|
end
|
64
|
-
|
99
|
+
|
100
|
+
def log_parse_error_once
|
101
|
+
@parse_error_logged ||= begin
|
102
|
+
parse_logger = logger || ActiveSupport::Logger.new($stderr)
|
103
|
+
parse_logger.debug <<~MSG.chomp
|
104
|
+
Error occurred while parsing request parameters.
|
105
|
+
Contents:
|
106
|
+
|
107
|
+
#{raw_post}
|
108
|
+
MSG
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def params_parsers
|
113
|
+
ActionDispatch::Request.parameter_parsers
|
114
|
+
end
|
65
115
|
end
|
66
116
|
end
|
67
117
|
end
|