actionpack 4.2.11.3 → 5.0.7.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 +890 -384
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/abstract_controller/base.rb +28 -38
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
- data/lib/abstract_controller/caching.rb +62 -0
- data/lib/abstract_controller/callbacks.rb +54 -19
- data/lib/abstract_controller/collector.rb +4 -9
- data/lib/abstract_controller/error.rb +4 -0
- data/lib/abstract_controller/helpers.rb +4 -3
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
- data/lib/abstract_controller/rendering.rb +28 -18
- data/lib/abstract_controller/translation.rb +8 -7
- data/lib/abstract_controller.rb +6 -2
- data/lib/action_controller/api/api_rendering.rb +14 -0
- data/lib/action_controller/api.rb +147 -0
- data/lib/action_controller/base.rb +14 -11
- data/lib/action_controller/caching.rb +13 -58
- data/lib/action_controller/form_builder.rb +48 -0
- data/lib/action_controller/log_subscriber.rb +3 -10
- data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
- data/lib/action_controller/metal/conditional_get.rb +106 -34
- data/lib/action_controller/metal/cookies.rb +1 -3
- data/lib/action_controller/metal/data_streaming.rb +14 -34
- data/lib/action_controller/metal/etag_with_template_digest.rb +8 -2
- data/lib/action_controller/metal/exceptions.rb +11 -6
- data/lib/action_controller/metal/force_ssl.rb +11 -11
- data/lib/action_controller/metal/head.rb +14 -8
- data/lib/action_controller/metal/helpers.rb +15 -6
- data/lib/action_controller/metal/http_authentication.rb +44 -35
- data/lib/action_controller/metal/implicit_render.rb +61 -6
- data/lib/action_controller/metal/instrumentation.rb +5 -5
- data/lib/action_controller/metal/live.rb +71 -88
- data/lib/action_controller/metal/mime_responds.rb +27 -42
- data/lib/action_controller/metal/params_wrapper.rb +9 -9
- data/lib/action_controller/metal/redirecting.rb +32 -9
- data/lib/action_controller/metal/renderers.rb +83 -40
- data/lib/action_controller/metal/rendering.rb +38 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
- data/lib/action_controller/metal/rescue.rb +3 -12
- data/lib/action_controller/metal/streaming.rb +4 -4
- data/lib/action_controller/metal/strong_parameters.rb +527 -134
- data/lib/action_controller/metal/testing.rb +1 -12
- data/lib/action_controller/metal/url_for.rb +12 -5
- data/lib/action_controller/metal.rb +88 -63
- data/lib/action_controller/railtie.rb +11 -7
- data/lib/action_controller/renderer.rb +113 -0
- data/lib/action_controller/template_assertions.rb +9 -0
- data/lib/action_controller/test_case.rb +311 -374
- data/lib/action_controller.rb +12 -9
- data/lib/action_dispatch/http/cache.rb +73 -34
- data/lib/action_dispatch/http/filter_parameters.rb +16 -12
- data/lib/action_dispatch/http/filter_redirect.rb +7 -8
- data/lib/action_dispatch/http/headers.rb +45 -14
- data/lib/action_dispatch/http/mime_negotiation.rb +42 -23
- data/lib/action_dispatch/http/mime_type.rb +126 -90
- data/lib/action_dispatch/http/mime_types.rb +3 -4
- data/lib/action_dispatch/http/parameter_filter.rb +19 -9
- data/lib/action_dispatch/http/parameters.rb +70 -40
- data/lib/action_dispatch/http/request.rb +144 -89
- data/lib/action_dispatch/http/response.rb +215 -102
- data/lib/action_dispatch/http/upload.rb +6 -2
- data/lib/action_dispatch/http/url.rb +117 -8
- data/lib/action_dispatch/journey/formatter.rb +47 -30
- data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
- data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
- data/lib/action_dispatch/journey/nodes/node.rb +14 -4
- data/lib/action_dispatch/journey/parser.rb +2 -0
- data/lib/action_dispatch/journey/parser_extras.rb +8 -2
- data/lib/action_dispatch/journey/path/pattern.rb +38 -42
- data/lib/action_dispatch/journey/route.rb +88 -26
- data/lib/action_dispatch/journey/router/utils.rb +5 -5
- data/lib/action_dispatch/journey/router.rb +8 -10
- data/lib/action_dispatch/journey/routes.rb +14 -15
- data/lib/action_dispatch/journey/visitors.rb +89 -44
- data/lib/action_dispatch/middleware/callbacks.rb +10 -1
- data/lib/action_dispatch/middleware/cookies.rb +188 -134
- data/lib/action_dispatch/middleware/debug_exceptions.rb +128 -49
- data/lib/action_dispatch/middleware/debug_locks.rb +122 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
- data/lib/action_dispatch/middleware/executor.rb +19 -0
- data/lib/action_dispatch/middleware/flash.rb +66 -45
- data/lib/action_dispatch/middleware/params_parser.rb +32 -46
- data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +14 -58
- data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
- data/lib/action_dispatch/middleware/request_id.rb +11 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
- data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
- data/lib/action_dispatch/middleware/ssl.rb +124 -36
- data/lib/action_dispatch/middleware/stack.rb +44 -40
- data/lib/action_dispatch/middleware/static.rb +51 -35
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.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 +59 -63
- data/lib/action_dispatch/railtie.rb +2 -2
- data/lib/action_dispatch/request/session.rb +69 -33
- data/lib/action_dispatch/request/utils.rb +51 -19
- data/lib/action_dispatch/routing/inspector.rb +32 -43
- data/lib/action_dispatch/routing/mapper.rb +515 -348
- data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
- data/lib/action_dispatch/routing/redirection.rb +5 -4
- data/lib/action_dispatch/routing/route_set.rb +148 -240
- data/lib/action_dispatch/routing/url_for.rb +27 -10
- data/lib/action_dispatch/routing.rb +17 -13
- data/lib/action_dispatch/testing/assertion_response.rb +45 -0
- data/lib/action_dispatch/testing/assertions/response.rb +38 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +16 -12
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +377 -149
- data/lib/action_dispatch/testing/request_encoder.rb +53 -0
- data/lib/action_dispatch/testing/test_process.rb +24 -20
- data/lib/action_dispatch/testing/test_request.rb +22 -31
- data/lib/action_dispatch/testing/test_response.rb +12 -4
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack.rb +1 -1
- metadata +32 -34
- 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/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +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
- /data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
@@ -1,23 +1,33 @@
|
|
1
|
-
|
1
|
+
# -*- frozen-string-literal: true -*-
|
2
|
+
|
2
3
|
require 'singleton'
|
3
4
|
require 'active_support/core_ext/module/attribute_accessors'
|
4
5
|
require 'active_support/core_ext/string/starts_ends_with'
|
5
6
|
|
6
7
|
module Mime
|
7
|
-
class Mimes
|
8
|
-
|
9
|
-
|
8
|
+
class Mimes
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@mimes = []
|
13
|
+
@symbols = nil
|
10
14
|
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def each
|
17
|
+
@mimes.each { |x| yield x }
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(type)
|
21
|
+
@mimes << type
|
22
|
+
@symbols = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_if
|
26
|
+
@mimes.delete_if { |x| yield x }.tap { @symbols = nil }
|
27
|
+
end
|
28
|
+
|
29
|
+
def symbols
|
30
|
+
@symbols ||= map(&:to_sym)
|
21
31
|
end
|
22
32
|
end
|
23
33
|
|
@@ -35,6 +45,32 @@ module Mime
|
|
35
45
|
return type if type.is_a?(Type)
|
36
46
|
EXTENSION_LOOKUP.fetch(type.to_s) { |k| yield k }
|
37
47
|
end
|
48
|
+
|
49
|
+
def const_missing(sym)
|
50
|
+
ext = sym.downcase
|
51
|
+
if Mime[ext]
|
52
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
53
|
+
Accessing mime types via constants is deprecated.
|
54
|
+
Please change `Mime::#{sym}` to `Mime[:#{ext}]`.
|
55
|
+
MSG
|
56
|
+
Mime[ext]
|
57
|
+
else
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def const_defined?(sym, inherit = true)
|
63
|
+
ext = sym.downcase
|
64
|
+
if Mime[ext]
|
65
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
66
|
+
Accessing mime types via constants is deprecated.
|
67
|
+
Please change `Mime.const_defined?(#{sym})` to `Mime[:#{ext}]`.
|
68
|
+
MSG
|
69
|
+
true
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
38
74
|
end
|
39
75
|
|
40
76
|
# Encapsulates the notion of a mime type. Can be used at render time, for example, with:
|
@@ -45,15 +81,12 @@ module Mime
|
|
45
81
|
#
|
46
82
|
# respond_to do |format|
|
47
83
|
# format.html
|
48
|
-
# format.ics { render
|
84
|
+
# format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") }
|
49
85
|
# format.xml { render xml: @post }
|
50
86
|
# end
|
51
87
|
# end
|
52
88
|
# end
|
53
89
|
class Type
|
54
|
-
@@html_types = Set.new [:html, :all]
|
55
|
-
cattr_reader :html_types
|
56
|
-
|
57
90
|
attr_reader :symbol
|
58
91
|
|
59
92
|
@register_callbacks = []
|
@@ -66,7 +99,7 @@ module Mime
|
|
66
99
|
def initialize(index, name, q = nil)
|
67
100
|
@index = index
|
68
101
|
@name = name
|
69
|
-
q ||= 0.0 if @name ==
|
102
|
+
q ||= 0.0 if @name == '*/*'.freeze # default wildcard match to end of list
|
70
103
|
@q = ((q || 1.0).to_f * 100).to_i
|
71
104
|
end
|
72
105
|
|
@@ -75,70 +108,58 @@ module Mime
|
|
75
108
|
result = @index <=> item.index if result == 0
|
76
109
|
result
|
77
110
|
end
|
78
|
-
|
79
|
-
def ==(item)
|
80
|
-
@name == item.to_s
|
81
|
-
end
|
82
111
|
end
|
83
112
|
|
84
|
-
class AcceptList
|
85
|
-
def
|
86
|
-
sort!
|
113
|
+
class AcceptList #:nodoc:
|
114
|
+
def self.sort!(list)
|
115
|
+
list.sort!
|
116
|
+
|
117
|
+
text_xml_idx = find_item_by_name list, 'text/xml'
|
118
|
+
app_xml_idx = find_item_by_name list, Mime[:xml].to_s
|
87
119
|
|
88
120
|
# Take care of the broken text/xml entry by renaming or deleting it
|
89
121
|
if text_xml_idx && app_xml_idx
|
122
|
+
app_xml = list[app_xml_idx]
|
123
|
+
text_xml = list[text_xml_idx]
|
124
|
+
|
90
125
|
app_xml.q = [text_xml.q, app_xml.q].max # set the q value to the max of the two
|
91
|
-
|
92
|
-
|
126
|
+
if app_xml_idx > text_xml_idx # make sure app_xml is ahead of text_xml in the list
|
127
|
+
list[app_xml_idx], list[text_xml_idx] = text_xml, app_xml
|
128
|
+
app_xml_idx, text_xml_idx = text_xml_idx, app_xml_idx
|
129
|
+
end
|
130
|
+
list.delete_at(text_xml_idx) # delete text_xml from the list
|
93
131
|
elsif text_xml_idx
|
94
|
-
|
132
|
+
list[text_xml_idx].name = Mime[:xml].to_s
|
95
133
|
end
|
96
134
|
|
97
135
|
# Look for more specific XML-based types and sort them ahead of app/xml
|
98
136
|
if app_xml_idx
|
137
|
+
app_xml = list[app_xml_idx]
|
99
138
|
idx = app_xml_idx
|
100
139
|
|
101
|
-
while idx < length
|
102
|
-
type =
|
140
|
+
while idx < list.length
|
141
|
+
type = list[idx]
|
103
142
|
break if type.q < app_xml.q
|
104
143
|
|
105
144
|
if type.name.ends_with? '+xml'
|
106
|
-
|
107
|
-
|
145
|
+
list[app_xml_idx], list[idx] = list[idx], app_xml
|
146
|
+
app_xml_idx = idx
|
108
147
|
end
|
109
148
|
idx += 1
|
110
149
|
end
|
111
150
|
end
|
112
151
|
|
113
|
-
map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
114
|
-
|
152
|
+
list.map! { |i| Mime::Type.lookup(i.name) }.uniq!
|
153
|
+
list
|
115
154
|
end
|
116
155
|
|
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
|
156
|
+
def self.find_item_by_name(array, name)
|
157
|
+
array.index { |item| item.name == name }
|
158
|
+
end
|
138
159
|
end
|
139
160
|
|
140
161
|
class << self
|
141
|
-
TRAILING_STAR_REGEXP =
|
162
|
+
TRAILING_STAR_REGEXP = /^(text|application)\/\*/
|
142
163
|
PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/
|
143
164
|
|
144
165
|
def register_callback(&block)
|
@@ -160,17 +181,17 @@ module Mime
|
|
160
181
|
end
|
161
182
|
|
162
183
|
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
163
|
-
|
184
|
+
new_mime = Type.new(string, symbol, mime_type_synonyms)
|
164
185
|
|
165
|
-
new_mime = Mime.const_get(symbol.upcase)
|
166
186
|
SET << new_mime
|
167
187
|
|
168
|
-
([string] + mime_type_synonyms).each { |str| LOOKUP[str] =
|
169
|
-
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] =
|
188
|
+
([string] + mime_type_synonyms).each { |str| LOOKUP[str] = new_mime } unless skip_lookup
|
189
|
+
([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = new_mime }
|
170
190
|
|
171
191
|
@register_callbacks.each do |callback|
|
172
192
|
callback.call(new_mime)
|
173
193
|
end
|
194
|
+
new_mime
|
174
195
|
end
|
175
196
|
|
176
197
|
def parse(accept_header)
|
@@ -178,21 +199,22 @@ module Mime
|
|
178
199
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
179
200
|
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
180
201
|
else
|
181
|
-
list, index =
|
202
|
+
list, index = [], 0
|
182
203
|
accept_header.split(',').each do |header|
|
183
204
|
params, q = header.split(PARAMETER_SEPARATOR_REGEXP)
|
184
|
-
if params.present?
|
185
|
-
params.strip!
|
186
205
|
|
187
|
-
|
206
|
+
next unless params
|
207
|
+
params.strip!
|
208
|
+
next if params.empty?
|
188
209
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
210
|
+
params = parse_trailing_star(params) || [params]
|
211
|
+
|
212
|
+
params.each do |m|
|
213
|
+
list << AcceptItem.new(index, m.to_s, q)
|
214
|
+
index += 1
|
193
215
|
end
|
194
216
|
end
|
195
|
-
|
217
|
+
AcceptList.sort! list
|
196
218
|
end
|
197
219
|
end
|
198
220
|
|
@@ -200,28 +222,27 @@ module Mime
|
|
200
222
|
parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
|
201
223
|
end
|
202
224
|
|
203
|
-
# For an input of <tt>'text'</tt>, returns <tt>[Mime
|
204
|
-
# Mime
|
225
|
+
# For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics],
|
226
|
+
# Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]</tt>.
|
205
227
|
#
|
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 =~
|
228
|
+
# For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js],
|
229
|
+
# Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>.
|
230
|
+
def parse_data_with_trailing_star(type)
|
231
|
+
Mime::SET.select { |m| m =~ type }
|
210
232
|
end
|
211
233
|
|
212
234
|
# This method is opposite of register method.
|
213
235
|
#
|
214
|
-
#
|
236
|
+
# To unregister a MIME type:
|
215
237
|
#
|
216
238
|
# Mime::Type.unregister(:mobile)
|
217
239
|
def unregister(symbol)
|
218
|
-
symbol = symbol.
|
219
|
-
mime = Mime
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
|
240
|
+
symbol = symbol.downcase
|
241
|
+
if mime = Mime[symbol]
|
242
|
+
SET.delete_if { |v| v.eql?(mime) }
|
243
|
+
LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
244
|
+
EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) }
|
245
|
+
end
|
225
246
|
end
|
226
247
|
end
|
227
248
|
|
@@ -246,7 +267,7 @@ module Mime
|
|
246
267
|
end
|
247
268
|
|
248
269
|
def ref
|
249
|
-
|
270
|
+
symbol || to_s
|
250
271
|
end
|
251
272
|
|
252
273
|
def ===(list)
|
@@ -258,7 +279,7 @@ module Mime
|
|
258
279
|
end
|
259
280
|
|
260
281
|
def ==(mime_type)
|
261
|
-
return false
|
282
|
+
return false unless mime_type
|
262
283
|
(@synonyms + [ self ]).any? do |synonym|
|
263
284
|
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
|
264
285
|
end
|
@@ -272,17 +293,16 @@ module Mime
|
|
272
293
|
end
|
273
294
|
|
274
295
|
def =~(mime_type)
|
275
|
-
return false
|
296
|
+
return false unless mime_type
|
276
297
|
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
|
277
|
-
|
278
|
-
synonym.to_s =~ regexp
|
279
|
-
end
|
298
|
+
@synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
|
280
299
|
end
|
281
300
|
|
282
301
|
def html?
|
283
|
-
|
302
|
+
symbol == :html || @string =~ /html/
|
284
303
|
end
|
285
304
|
|
305
|
+
def all?; false; end
|
286
306
|
|
287
307
|
protected
|
288
308
|
|
@@ -306,6 +326,22 @@ module Mime
|
|
306
326
|
end
|
307
327
|
end
|
308
328
|
|
329
|
+
class AllType < Type
|
330
|
+
include Singleton
|
331
|
+
|
332
|
+
def initialize
|
333
|
+
super '*/*', :all
|
334
|
+
end
|
335
|
+
|
336
|
+
def all?; true; end
|
337
|
+
def html?; true; end
|
338
|
+
end
|
339
|
+
|
340
|
+
# ALL isn't a real MIME type, so we don't register it for lookup with the
|
341
|
+
# other concrete types. It's a wildcard match that we use for `respond_to`
|
342
|
+
# negotiation internals.
|
343
|
+
ALL = AllType.instance
|
344
|
+
|
309
345
|
class NullType
|
310
346
|
include Singleton
|
311
347
|
|
@@ -14,13 +14,14 @@ Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe pjpeg)
|
|
14
14
|
Mime::Type.register "image/gif", :gif, [], %w(gif)
|
15
15
|
Mime::Type.register "image/bmp", :bmp, [], %w(bmp)
|
16
16
|
Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff)
|
17
|
+
Mime::Type.register "image/svg+xml", :svg
|
17
18
|
|
18
19
|
Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe)
|
19
20
|
|
20
21
|
Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml )
|
21
22
|
Mime::Type.register "application/rss+xml", :rss
|
22
23
|
Mime::Type.register "application/atom+xml", :atom
|
23
|
-
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml )
|
24
|
+
Mime::Type.register "application/x-yaml", :yaml, %w( text/yaml ), %w(yml yaml)
|
24
25
|
|
25
26
|
Mime::Type.register "multipart/form-data", :multipart_form
|
26
27
|
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
|
@@ -31,6 +32,4 @@ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonr
|
|
31
32
|
|
32
33
|
Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
|
33
34
|
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, [])
|
35
|
+
Mime::Type.register "application/gzip", :gzip, %w(application/x-gzip), %w(gz)
|
@@ -30,36 +30,46 @@ module ActionDispatch
|
|
30
30
|
when Regexp
|
31
31
|
regexps << item
|
32
32
|
else
|
33
|
-
strings << item.to_s
|
33
|
+
strings << Regexp.escape(item.to_s)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
regexps
|
38
|
-
|
37
|
+
deep_regexps, regexps = regexps.partition { |r| r.to_s.include?("\\.".freeze) }
|
38
|
+
deep_strings, strings = strings.partition { |s| s.include?("\\.".freeze) }
|
39
|
+
|
40
|
+
regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty?
|
41
|
+
deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty?
|
42
|
+
|
43
|
+
new regexps, deep_regexps, blocks
|
39
44
|
end
|
40
45
|
|
41
|
-
attr_reader :regexps, :blocks
|
46
|
+
attr_reader :regexps, :deep_regexps, :blocks
|
42
47
|
|
43
|
-
def initialize(regexps, blocks)
|
48
|
+
def initialize(regexps, deep_regexps, blocks)
|
44
49
|
@regexps = regexps
|
50
|
+
@deep_regexps = deep_regexps.any? ? deep_regexps : nil
|
45
51
|
@blocks = blocks
|
46
52
|
end
|
47
53
|
|
48
|
-
def call(original_params)
|
49
|
-
filtered_params =
|
54
|
+
def call(original_params, parents = [])
|
55
|
+
filtered_params = original_params.class.new
|
50
56
|
|
51
57
|
original_params.each do |key, value|
|
58
|
+
parents.push(key) if deep_regexps
|
52
59
|
if regexps.any? { |r| key =~ r }
|
53
60
|
value = FILTERED
|
61
|
+
elsif deep_regexps && (joined = parents.join('.')) && deep_regexps.any? { |r| joined =~ r }
|
62
|
+
value = FILTERED
|
54
63
|
elsif value.is_a?(Hash)
|
55
|
-
value = call(value)
|
64
|
+
value = call(value, parents)
|
56
65
|
elsif value.is_a?(Array)
|
57
|
-
value = value.map { |v| v.is_a?(Hash) ? call(v) : v }
|
66
|
+
value = value.map { |v| v.is_a?(Hash) ? call(v, parents) : v }
|
58
67
|
elsif blocks.any?
|
59
68
|
key = key.dup if key.duplicable?
|
60
69
|
value = value.dup if value.duplicable?
|
61
70
|
blocks.each { |b| b.call(key, value) }
|
62
71
|
end
|
72
|
+
parents.pop if deep_regexps
|
63
73
|
|
64
74
|
filtered_params[key] = value
|
65
75
|
end
|
@@ -1,35 +1,67 @@
|
|
1
|
-
require 'active_support/core_ext/hash/keys'
|
2
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
-
require 'active_support/deprecation'
|
4
|
-
|
5
1
|
module ActionDispatch
|
6
2
|
module Http
|
7
3
|
module Parameters
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
8
6
|
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
|
9
7
|
|
8
|
+
DEFAULT_PARSERS = {
|
9
|
+
Mime[:json].symbol => -> (raw_post) {
|
10
|
+
data = ActiveSupport::JSON.decode(raw_post)
|
11
|
+
data.is_a?(Hash) ? data : {:_json => data}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
included do
|
16
|
+
class << self
|
17
|
+
# Returns the parameter parsers.
|
18
|
+
attr_reader :parameter_parsers
|
19
|
+
end
|
20
|
+
|
21
|
+
self.parameter_parsers = DEFAULT_PARSERS
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
# Configure the parameter parser for a give mime type.
|
26
|
+
#
|
27
|
+
# It accepts a hash where the key is the symbol of the mime type
|
28
|
+
# and the value is a proc.
|
29
|
+
#
|
30
|
+
# original_parsers = ActionDispatch::Request.parameter_parsers
|
31
|
+
# xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
|
32
|
+
# new_parsers = original_parsers.merge(xml: xml_parser)
|
33
|
+
# ActionDispatch::Request.parameter_parsers = new_parsers
|
34
|
+
def parameter_parsers=(parsers)
|
35
|
+
@parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
10
39
|
# Returns both GET and POST \parameters in a single hash.
|
11
40
|
def parameters
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
41
|
+
params = get_header("action_dispatch.request.parameters")
|
42
|
+
return params if params
|
43
|
+
|
44
|
+
params = begin
|
45
|
+
request_parameters.merge(query_parameters)
|
46
|
+
rescue EOFError
|
47
|
+
query_parameters.dup
|
48
|
+
end
|
49
|
+
params.merge!(path_parameters)
|
50
|
+
set_header("action_dispatch.request.parameters", params)
|
51
|
+
params
|
20
52
|
end
|
21
53
|
alias :params :parameters
|
22
54
|
|
23
55
|
def path_parameters=(parameters) #:nodoc:
|
24
|
-
|
25
|
-
@env[PARAMETERS_KEY] = parameters
|
26
|
-
end
|
56
|
+
delete_header('action_dispatch.request.parameters')
|
27
57
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
58
|
+
# If any of the path parameters has an invalid encoding then
|
59
|
+
# raise since it's likely to trigger errors further on.
|
60
|
+
Request::Utils.check_param_encoding(parameters)
|
61
|
+
|
62
|
+
set_header PARAMETERS_KEY, parameters
|
63
|
+
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
|
64
|
+
raise ActionController::BadRequest.new("Invalid path parameters: #{e.message}")
|
33
65
|
end
|
34
66
|
|
35
67
|
# Returns a hash with the \parameters used to form the \path of the request.
|
@@ -37,31 +69,29 @@ module ActionDispatch
|
|
37
69
|
#
|
38
70
|
# {'action' => 'my_action', 'controller' => 'my_controller'}
|
39
71
|
def path_parameters
|
40
|
-
|
72
|
+
get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
|
41
73
|
end
|
42
74
|
|
43
|
-
|
75
|
+
private
|
44
76
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
normalize_encode_params(val)
|
58
|
-
end
|
59
|
-
end.with_indifferent_access
|
60
|
-
end
|
61
|
-
else
|
62
|
-
params
|
77
|
+
def parse_formatted_parameters(parsers)
|
78
|
+
return yield if content_length.zero? || content_mime_type.nil?
|
79
|
+
|
80
|
+
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
|
81
|
+
|
82
|
+
begin
|
83
|
+
strategy.call(raw_post)
|
84
|
+
rescue # JSON or Ruby code block errors
|
85
|
+
my_logger = logger || ActiveSupport::Logger.new($stderr)
|
86
|
+
my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
|
87
|
+
|
88
|
+
raise ParamsParser::ParseError
|
63
89
|
end
|
64
90
|
end
|
91
|
+
|
92
|
+
def params_parsers
|
93
|
+
ActionDispatch::Request.parameter_parsers
|
94
|
+
end
|
65
95
|
end
|
66
96
|
end
|
67
97
|
end
|