actionpack 4.0.1 → 4.2.11.1
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 +402 -1173
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/lib/abstract_controller/base.rb +39 -7
- data/lib/abstract_controller/callbacks.rb +32 -53
- data/lib/abstract_controller/collector.rb +11 -1
- data/lib/abstract_controller/helpers.rb +26 -16
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/rendering.rb +57 -127
- data/lib/abstract_controller/url_for.rb +1 -1
- data/lib/abstract_controller.rb +1 -2
- data/lib/action_controller/base.rb +19 -10
- data/lib/action_controller/caching/fragments.rb +7 -1
- data/lib/action_controller/caching.rb +2 -12
- data/lib/action_controller/log_subscriber.rb +29 -20
- data/lib/action_controller/metal/conditional_get.rb +37 -12
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +1 -1
- data/lib/action_controller/metal/flash.rb +17 -0
- data/lib/action_controller/metal/force_ssl.rb +2 -2
- data/lib/action_controller/metal/head.rb +8 -6
- data/lib/action_controller/metal/helpers.rb +6 -2
- data/lib/action_controller/metal/http_authentication.rb +45 -23
- data/lib/action_controller/metal/instrumentation.rb +9 -6
- data/lib/action_controller/metal/live.rb +173 -20
- data/lib/action_controller/metal/mime_responds.rb +127 -232
- data/lib/action_controller/metal/params_wrapper.rb +16 -9
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +34 -26
- data/lib/action_controller/metal/renderers.rb +39 -12
- data/lib/action_controller/metal/rendering.rb +41 -14
- data/lib/action_controller/metal/request_forgery_protection.rb +147 -19
- data/lib/action_controller/metal/streaming.rb +19 -21
- data/lib/action_controller/metal/strong_parameters.rb +166 -22
- data/lib/action_controller/metal/testing.rb +0 -1
- data/lib/action_controller/metal/url_for.rb +11 -12
- data/lib/action_controller/metal.rb +14 -8
- data/lib/action_controller/model_naming.rb +1 -1
- data/lib/action_controller/railtie.rb +5 -1
- data/lib/action_controller/test_case.rb +160 -94
- data/lib/action_controller.rb +2 -18
- data/lib/action_dispatch/http/cache.rb +5 -4
- data/lib/action_dispatch/http/filter_parameters.rb +2 -2
- data/lib/action_dispatch/http/filter_redirect.rb +5 -4
- data/lib/action_dispatch/http/headers.rb +46 -10
- data/lib/action_dispatch/http/mime_negotiation.rb +31 -4
- data/lib/action_dispatch/http/mime_type.rb +25 -26
- data/lib/action_dispatch/http/mime_types.rb +1 -0
- data/lib/action_dispatch/http/parameter_filter.rb +1 -1
- data/lib/action_dispatch/http/parameters.rb +25 -41
- data/lib/action_dispatch/http/request.rb +49 -32
- data/lib/action_dispatch/http/response.rb +127 -25
- data/lib/action_dispatch/http/upload.rb +9 -21
- data/lib/action_dispatch/http/url.rb +97 -70
- data/lib/action_dispatch/journey/formatter.rb +35 -19
- data/lib/action_dispatch/journey/gtg/builder.rb +3 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -33
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
- data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -5
- data/lib/action_dispatch/journey/nodes/node.rb +4 -0
- data/lib/action_dispatch/journey/parser.rb +51 -59
- data/lib/action_dispatch/journey/parser.y +12 -10
- data/lib/action_dispatch/journey/path/pattern.rb +16 -19
- data/lib/action_dispatch/journey/route.rb +8 -19
- data/lib/action_dispatch/journey/router/strexp.rb +9 -6
- data/lib/action_dispatch/journey/router/utils.rb +54 -18
- data/lib/action_dispatch/journey/router.rb +53 -75
- data/lib/action_dispatch/journey/routes.rb +4 -0
- data/lib/action_dispatch/journey/scanner.rb +5 -5
- data/lib/action_dispatch/journey/visitors.rb +81 -60
- data/lib/action_dispatch/journey/visualizer/fsm.css +0 -4
- data/lib/action_dispatch/journey/visualizer/index.html.erb +2 -2
- data/lib/action_dispatch/middleware/callbacks.rb +7 -7
- data/lib/action_dispatch/middleware/cookies.rb +119 -43
- data/lib/action_dispatch/middleware/debug_exceptions.rb +32 -13
- data/lib/action_dispatch/middleware/exception_wrapper.rb +60 -20
- data/lib/action_dispatch/middleware/flash.rb +37 -24
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +12 -3
- data/lib/action_dispatch/middleware/reloader.rb +11 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +40 -54
- data/lib/action_dispatch/middleware/request_id.rb +1 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +8 -7
- data/lib/action_dispatch/middleware/show_exceptions.rb +6 -2
- data/lib/action_dispatch/middleware/ssl.rb +10 -7
- data/lib/action_dispatch/middleware/static.rb +79 -23
- data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +21 -19
- 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.erb → diagnostics.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +6 -0
- 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.erb → routing_error.html.erb} +3 -1
- 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.erb → unknown_action.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +120 -64
- data/lib/action_dispatch/railtie.rb +5 -2
- data/lib/action_dispatch/request/session.rb +12 -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 +11 -17
- data/lib/action_dispatch/routing/mapper.rb +519 -312
- data/lib/action_dispatch/routing/polymorphic_routes.rb +204 -79
- data/lib/action_dispatch/routing/redirection.rb +51 -26
- data/lib/action_dispatch/routing/route_set.rb +331 -206
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -4
- data/lib/action_dispatch/routing/url_for.rb +19 -5
- data/lib/action_dispatch/routing.rb +9 -6
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -26
- data/lib/action_dispatch/testing/assertions/response.rb +9 -15
- data/lib/action_dispatch/testing/assertions/routing.rb +22 -22
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -429
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -134
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +31 -29
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- data/lib/action_dispatch.rb +5 -8
- data/lib/action_pack/gem_version.rb +15 -0
- data/lib/action_pack/version.rb +4 -7
- data/lib/action_pack.rb +1 -1
- metadata +77 -159
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/deprecated/integration_test.rb +0 -5
- data/lib/action_controller/deprecated.rb +0 -7
- data/lib/action_controller/metal/responder.rb +0 -287
- data/lib/action_controller/record_identifier.rb +0 -31
- data/lib/action_controller/vendor/html-scanner.rb +0 -5
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -24
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -43
- data/lib/action_view/base.rb +0 -201
- data/lib/action_view/buffers.rb +0 -49
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/dependency_tracker.rb +0 -93
- data/lib/action_view/digestor.rb +0 -113
- data/lib/action_view/flows.rb +0 -76
- data/lib/action_view/helpers/active_model_helper.rb +0 -49
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
- data/lib/action_view/helpers/asset_url_helper.rb +0 -355
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
- data/lib/action_view/helpers/cache_helper.rb +0 -196
- data/lib/action_view/helpers/capture_helper.rb +0 -216
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -30
- data/lib/action_view/helpers/date_helper.rb +0 -1083
- data/lib/action_view/helpers/debug_helper.rb +0 -39
- data/lib/action_view/helpers/form_helper.rb +0 -1880
- data/lib/action_view/helpers/form_options_helper.rb +0 -838
- data/lib/action_view/helpers/form_tag_helper.rb +0 -785
- data/lib/action_view/helpers/javascript_helper.rb +0 -117
- data/lib/action_view/helpers/number_helper.rb +0 -441
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -106
- data/lib/action_view/helpers/rendering_helper.rb +0 -90
- data/lib/action_view/helpers/sanitize_helper.rb +0 -256
- data/lib/action_view/helpers/tag_helper.rb +0 -173
- data/lib/action_view/helpers/tags/base.rb +0 -148
- data/lib/action_view/helpers/tags/check_box.rb +0 -64
- data/lib/action_view/helpers/tags/checkable.rb +0 -16
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -44
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
- data/lib/action_view/helpers/tags/collection_select.rb +0 -28
- data/lib/action_view/helpers/tags/color_field.rb +0 -25
- data/lib/action_view/helpers/tags/date_field.rb +0 -13
- data/lib/action_view/helpers/tags/date_select.rb +0 -72
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
- data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
- data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
- data/lib/action_view/helpers/tags/email_field.rb +0 -8
- data/lib/action_view/helpers/tags/file_field.rb +0 -8
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
- data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
- data/lib/action_view/helpers/tags/label.rb +0 -66
- data/lib/action_view/helpers/tags/month_field.rb +0 -13
- data/lib/action_view/helpers/tags/number_field.rb +0 -18
- data/lib/action_view/helpers/tags/password_field.rb +0 -12
- data/lib/action_view/helpers/tags/radio_button.rb +0 -31
- data/lib/action_view/helpers/tags/range_field.rb +0 -8
- data/lib/action_view/helpers/tags/search_field.rb +0 -24
- data/lib/action_view/helpers/tags/select.rb +0 -40
- data/lib/action_view/helpers/tags/tel_field.rb +0 -8
- data/lib/action_view/helpers/tags/text_area.rb +0 -18
- data/lib/action_view/helpers/tags/text_field.rb +0 -29
- data/lib/action_view/helpers/tags/time_field.rb +0 -13
- data/lib/action_view/helpers/tags/time_select.rb +0 -8
- data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
- data/lib/action_view/helpers/tags/url_field.rb +0 -8
- data/lib/action_view/helpers/tags/week_field.rb +0 -13
- data/lib/action_view/helpers/tags.rb +0 -39
- data/lib/action_view/helpers/text_helper.rb +0 -443
- data/lib/action_view/helpers/translation_helper.rb +0 -107
- data/lib/action_view/helpers/url_helper.rb +0 -635
- data/lib/action_view/helpers.rb +0 -58
- data/lib/action_view/locale/en.yml +0 -56
- data/lib/action_view/log_subscriber.rb +0 -30
- data/lib/action_view/lookup_context.rb +0 -241
- data/lib/action_view/model_naming.rb +0 -12
- data/lib/action_view/path_set.rb +0 -77
- data/lib/action_view/railtie.rb +0 -43
- data/lib/action_view/record_identifier.rb +0 -84
- data/lib/action_view/renderer/abstract_renderer.rb +0 -47
- data/lib/action_view/renderer/partial_renderer.rb +0 -492
- data/lib/action_view/renderer/renderer.rb +0 -50
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
- data/lib/action_view/renderer/template_renderer.rb +0 -96
- data/lib/action_view/routing_url_for.rb +0 -107
- data/lib/action_view/tasks/dependencies.rake +0 -17
- data/lib/action_view/template/error.rb +0 -138
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -146
- data/lib/action_view/template/handlers/raw.rb +0 -11
- data/lib/action_view/template/handlers.rb +0 -53
- data/lib/action_view/template/resolver.rb +0 -326
- data/lib/action_view/template/text.rb +0 -34
- data/lib/action_view/template/types.rb +0 -57
- data/lib/action_view/template.rb +0 -339
- data/lib/action_view/test_case.rb +0 -270
- data/lib/action_view/testing/resolvers.rb +0 -50
- data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
- data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_view/vendor/html-scanner.rb +0 -20
- data/lib/action_view.rb +0 -93
@@ -1,4 +1,7 @@
|
|
1
|
-
require 'active_support/core_ext/
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
require 'active_support/core_ext/string/filters'
|
3
|
+
require 'active_support/deprecation'
|
4
|
+
require 'action_dispatch/http/filter_redirect'
|
2
5
|
require 'monitor'
|
3
6
|
|
4
7
|
module ActionDispatch # :nodoc:
|
@@ -31,10 +34,17 @@ module ActionDispatch # :nodoc:
|
|
31
34
|
# end
|
32
35
|
# end
|
33
36
|
class Response
|
34
|
-
|
37
|
+
# The request that the response is responding to.
|
38
|
+
attr_accessor :request
|
39
|
+
|
40
|
+
# The HTTP status code.
|
35
41
|
attr_reader :status
|
42
|
+
|
36
43
|
attr_writer :sending_file
|
37
44
|
|
45
|
+
# Get and set headers for this response.
|
46
|
+
attr_accessor :header
|
47
|
+
|
38
48
|
alias_method :headers=, :header=
|
39
49
|
alias_method :headers, :header
|
40
50
|
|
@@ -49,9 +59,12 @@ module ActionDispatch # :nodoc:
|
|
49
59
|
# If a character set has been defined for this response (see charset=) then
|
50
60
|
# the character set information will also be included in the content type
|
51
61
|
# information.
|
52
|
-
attr_accessor :charset
|
53
62
|
attr_reader :content_type
|
54
63
|
|
64
|
+
# The charset of the response. HTML wants to know the encoding of the
|
65
|
+
# content you're giving them, so we need to send that along.
|
66
|
+
attr_accessor :charset
|
67
|
+
|
55
68
|
CONTENT_TYPE = "Content-Type".freeze
|
56
69
|
SET_COOKIE = "Set-Cookie".freeze
|
57
70
|
LOCATION = "Location".freeze
|
@@ -80,7 +93,13 @@ module ActionDispatch # :nodoc:
|
|
80
93
|
end
|
81
94
|
|
82
95
|
def each(&block)
|
83
|
-
@
|
96
|
+
@response.sending!
|
97
|
+
x = @buf.each(&block)
|
98
|
+
@response.sent!
|
99
|
+
x
|
100
|
+
end
|
101
|
+
|
102
|
+
def abort
|
84
103
|
end
|
85
104
|
|
86
105
|
def close
|
@@ -93,12 +112,14 @@ module ActionDispatch # :nodoc:
|
|
93
112
|
end
|
94
113
|
end
|
95
114
|
|
115
|
+
# The underlying body, as a streamable object.
|
96
116
|
attr_reader :stream
|
97
117
|
|
98
|
-
def initialize(status = 200, header = {}, body = [])
|
118
|
+
def initialize(status = 200, header = {}, body = [], options = {})
|
99
119
|
super()
|
100
120
|
|
101
|
-
|
121
|
+
default_headers = options.fetch(:default_headers, self.class.default_headers)
|
122
|
+
header = merge_default_headers(header, default_headers)
|
102
123
|
|
103
124
|
self.body, self.header, self.status = body, header, status
|
104
125
|
|
@@ -106,6 +127,8 @@ module ActionDispatch # :nodoc:
|
|
106
127
|
@blank = false
|
107
128
|
@cv = new_cond
|
108
129
|
@committed = false
|
130
|
+
@sending = false
|
131
|
+
@sent = false
|
109
132
|
@content_type = nil
|
110
133
|
@charset = nil
|
111
134
|
|
@@ -126,22 +149,43 @@ module ActionDispatch # :nodoc:
|
|
126
149
|
end
|
127
150
|
end
|
128
151
|
|
152
|
+
def await_sent
|
153
|
+
synchronize { @cv.wait_until { @sent } }
|
154
|
+
end
|
155
|
+
|
129
156
|
def commit!
|
130
157
|
synchronize do
|
158
|
+
before_committed
|
131
159
|
@committed = true
|
132
160
|
@cv.broadcast
|
133
161
|
end
|
134
162
|
end
|
135
163
|
|
136
|
-
def
|
137
|
-
|
164
|
+
def sending!
|
165
|
+
synchronize do
|
166
|
+
before_sending
|
167
|
+
@sending = true
|
168
|
+
@cv.broadcast
|
169
|
+
end
|
138
170
|
end
|
139
171
|
|
172
|
+
def sent!
|
173
|
+
synchronize do
|
174
|
+
@sent = true
|
175
|
+
@cv.broadcast
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def sending?; synchronize { @sending }; end
|
180
|
+
def committed?; synchronize { @committed }; end
|
181
|
+
def sent?; synchronize { @sent }; end
|
182
|
+
|
140
183
|
# Sets the HTTP status code.
|
141
184
|
def status=(status)
|
142
185
|
@status = Rack::Utils.status_code(status)
|
143
186
|
end
|
144
187
|
|
188
|
+
# Sets the HTTP content type.
|
145
189
|
def content_type=(content_type)
|
146
190
|
@content_type = content_type.to_s
|
147
191
|
end
|
@@ -169,18 +213,6 @@ module ActionDispatch # :nodoc:
|
|
169
213
|
end
|
170
214
|
alias_method :status_message, :message
|
171
215
|
|
172
|
-
def respond_to?(method)
|
173
|
-
if method.to_s == 'to_path'
|
174
|
-
stream.respond_to?(:to_path)
|
175
|
-
else
|
176
|
-
super
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def to_path
|
181
|
-
stream.to_path
|
182
|
-
end
|
183
|
-
|
184
216
|
# Returns the content of the response as a string. This contains the contents
|
185
217
|
# of any calls to <tt>render</tt>.
|
186
218
|
def body
|
@@ -218,11 +250,13 @@ module ActionDispatch # :nodoc:
|
|
218
250
|
::Rack::Utils.delete_cookie_header!(header, key, value)
|
219
251
|
end
|
220
252
|
|
253
|
+
# The location header we'll be responding with.
|
221
254
|
def location
|
222
255
|
headers[LOCATION]
|
223
256
|
end
|
224
257
|
alias_method :redirect_url, :location
|
225
258
|
|
259
|
+
# Sets the location header we'll be responding with.
|
226
260
|
def location=(url)
|
227
261
|
headers[LOCATION] = url
|
228
262
|
end
|
@@ -231,11 +265,39 @@ module ActionDispatch # :nodoc:
|
|
231
265
|
stream.close if stream.respond_to?(:close)
|
232
266
|
end
|
233
267
|
|
268
|
+
def abort
|
269
|
+
if stream.respond_to?(:abort)
|
270
|
+
stream.abort
|
271
|
+
elsif stream.respond_to?(:close)
|
272
|
+
# `stream.close` should really be reserved for a close from the
|
273
|
+
# other direction, but we must fall back to it for
|
274
|
+
# compatibility.
|
275
|
+
stream.close
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Turns the Response into a Rack-compatible array of the status, headers,
|
280
|
+
# and body. Allows explict splatting:
|
281
|
+
#
|
282
|
+
# status, headers, body = *response
|
234
283
|
def to_a
|
235
284
|
rack_response @status, @header.to_hash
|
236
285
|
end
|
237
286
|
alias prepare! to_a
|
238
|
-
|
287
|
+
|
288
|
+
# Be super clear that a response object is not an Array. Defining this
|
289
|
+
# would make implicit splatting work, but it also makes adding responses
|
290
|
+
# as arrays work, and "flattening" responses, cascading to the rack body!
|
291
|
+
# Not sensible behavior.
|
292
|
+
def to_ary
|
293
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
294
|
+
`ActionDispatch::Response#to_ary` no longer performs implicit conversion
|
295
|
+
to an array. Please use `response.to_a` instead, or a splat like `status,
|
296
|
+
headers, body = *response`.
|
297
|
+
MSG
|
298
|
+
|
299
|
+
to_a
|
300
|
+
end
|
239
301
|
|
240
302
|
# Returns the response cookies, converted to a Hash of (name => value) pairs
|
241
303
|
#
|
@@ -256,10 +318,14 @@ module ActionDispatch # :nodoc:
|
|
256
318
|
|
257
319
|
private
|
258
320
|
|
259
|
-
def
|
260
|
-
|
321
|
+
def before_committed
|
322
|
+
end
|
323
|
+
|
324
|
+
def before_sending
|
325
|
+
end
|
261
326
|
|
262
|
-
|
327
|
+
def merge_default_headers(original, default)
|
328
|
+
default.respond_to?(:merge) ? default.merge(original) : original
|
263
329
|
end
|
264
330
|
|
265
331
|
def build_buffer(response, body)
|
@@ -286,6 +352,42 @@ module ActionDispatch # :nodoc:
|
|
286
352
|
!@sending_file && @charset != false
|
287
353
|
end
|
288
354
|
|
355
|
+
class RackBody
|
356
|
+
def initialize(response)
|
357
|
+
@response = response
|
358
|
+
end
|
359
|
+
|
360
|
+
def each(*args, &block)
|
361
|
+
@response.each(*args, &block)
|
362
|
+
end
|
363
|
+
|
364
|
+
def close
|
365
|
+
# Rack "close" maps to Response#abort, and *not* Response#close
|
366
|
+
# (which is used when the controller's finished writing)
|
367
|
+
@response.abort
|
368
|
+
end
|
369
|
+
|
370
|
+
def body
|
371
|
+
@response.body
|
372
|
+
end
|
373
|
+
|
374
|
+
def respond_to?(method, include_private = false)
|
375
|
+
if method.to_s == 'to_path'
|
376
|
+
@response.stream.respond_to?(method)
|
377
|
+
else
|
378
|
+
super
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def to_path
|
383
|
+
@response.stream.to_path
|
384
|
+
end
|
385
|
+
|
386
|
+
def to_ary
|
387
|
+
nil
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
289
391
|
def rack_response(status, header)
|
290
392
|
assign_default_content_type_and_charset!(header)
|
291
393
|
handle_conditional_get!
|
@@ -296,7 +398,7 @@ module ActionDispatch # :nodoc:
|
|
296
398
|
header.delete CONTENT_TYPE
|
297
399
|
[status, header, []]
|
298
400
|
else
|
299
|
-
[status, header, self]
|
401
|
+
[status, header, RackBody.new(self)]
|
300
402
|
end
|
301
403
|
end
|
302
404
|
end
|
@@ -18,6 +18,7 @@ module ActionDispatch
|
|
18
18
|
# A +Tempfile+ object with the actual uploaded file. Note that some of
|
19
19
|
# its interface is available directly.
|
20
20
|
attr_accessor :tempfile
|
21
|
+
alias :to_io :tempfile
|
21
22
|
|
22
23
|
# A string with the headers of the multipart request.
|
23
24
|
attr_accessor :headers
|
@@ -26,7 +27,14 @@ module ActionDispatch
|
|
26
27
|
@tempfile = hash[:tempfile]
|
27
28
|
raise(ArgumentError, ':tempfile is required') unless @tempfile
|
28
29
|
|
29
|
-
@original_filename =
|
30
|
+
@original_filename = hash[:filename]
|
31
|
+
if @original_filename
|
32
|
+
begin
|
33
|
+
@original_filename.encode!(Encoding::UTF_8)
|
34
|
+
rescue EncodingError
|
35
|
+
@original_filename.force_encoding(Encoding::UTF_8)
|
36
|
+
end
|
37
|
+
end
|
30
38
|
@content_type = hash[:type]
|
31
39
|
@headers = hash[:head]
|
32
40
|
end
|
@@ -65,26 +73,6 @@ module ActionDispatch
|
|
65
73
|
def eof?
|
66
74
|
@tempfile.eof?
|
67
75
|
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def encode_filename(filename)
|
72
|
-
# Encode the filename in the utf8 encoding, unless it is nil
|
73
|
-
filename.force_encoding(Encoding::UTF_8).encode! if filename
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
module Upload # :nodoc:
|
78
|
-
# Replace file upload hash with UploadedFile objects
|
79
|
-
# when normalize and encode parameters.
|
80
|
-
def normalize_encode_params(value)
|
81
|
-
if Hash === value && value.has_key?(:tempfile)
|
82
|
-
UploadedFile.new(value)
|
83
|
-
else
|
84
|
-
super
|
85
|
-
end
|
86
|
-
end
|
87
|
-
private :normalize_encode_params
|
88
76
|
end
|
89
77
|
end
|
90
78
|
end
|
@@ -5,99 +5,123 @@ module ActionDispatch
|
|
5
5
|
module Http
|
6
6
|
module URL
|
7
7
|
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
|
8
|
-
HOST_REGEXP = /(
|
8
|
+
HOST_REGEXP = /(^[^:]+:\/\/)?(\[[^\]]+\]|[^:]+)(?::(\d+$))?/
|
9
9
|
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
|
10
10
|
|
11
11
|
mattr_accessor :tld_length
|
12
12
|
self.tld_length = 1
|
13
13
|
|
14
14
|
class << self
|
15
|
-
def extract_domain(host, tld_length
|
16
|
-
host
|
15
|
+
def extract_domain(host, tld_length)
|
16
|
+
extract_domain_from(host, tld_length) if named_host?(host)
|
17
17
|
end
|
18
18
|
|
19
|
-
def extract_subdomains(host, tld_length
|
19
|
+
def extract_subdomains(host, tld_length)
|
20
20
|
if named_host?(host)
|
21
|
-
|
22
|
-
parts[0..-(tld_length + 2)]
|
21
|
+
extract_subdomains_from(host, tld_length)
|
23
22
|
else
|
24
23
|
[]
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
|
-
def extract_subdomain(host, tld_length
|
27
|
+
def extract_subdomain(host, tld_length)
|
29
28
|
extract_subdomains(host, tld_length).join('.')
|
30
29
|
end
|
31
30
|
|
32
|
-
def url_for(options
|
33
|
-
|
34
|
-
|
35
|
-
path << options.delete(:path).to_s
|
36
|
-
|
37
|
-
params = options[:params].is_a?(Hash) ? options[:params] : options.slice(:params)
|
38
|
-
params.reject! { |_,v| v.to_param.nil? }
|
39
|
-
|
40
|
-
result = build_host_url(options)
|
41
|
-
if options[:trailing_slash]
|
42
|
-
if path.include?('?')
|
43
|
-
result << path.sub(/\?/, '/\&')
|
44
|
-
else
|
45
|
-
result << path.sub(/[^\/]\z|\A\z/, '\&/')
|
46
|
-
end
|
31
|
+
def url_for(options)
|
32
|
+
if options[:only_path]
|
33
|
+
path_for options
|
47
34
|
else
|
48
|
-
|
35
|
+
full_url_for options
|
49
36
|
end
|
50
|
-
result << "?#{params.to_query}" unless params.empty?
|
51
|
-
result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
|
52
|
-
result
|
53
37
|
end
|
54
38
|
|
55
|
-
|
39
|
+
def full_url_for(options)
|
40
|
+
host = options[:host]
|
41
|
+
protocol = options[:protocol]
|
42
|
+
port = options[:port]
|
56
43
|
|
57
|
-
|
58
|
-
if options[:host].blank? && options[:only_path].blank?
|
44
|
+
unless host
|
59
45
|
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
|
60
46
|
end
|
61
47
|
|
62
|
-
|
48
|
+
build_host_url(host, port, protocol, options, path_for(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
def path_for(options)
|
52
|
+
path = options[:script_name].to_s.chomp("/")
|
53
|
+
path << options[:path] if options.key?(:path)
|
54
|
+
|
55
|
+
add_trailing_slash(path) if options[:trailing_slash]
|
56
|
+
add_params(path, options[:params]) if options.key?(:params)
|
57
|
+
add_anchor(path, options[:anchor]) if options.key?(:anchor)
|
63
58
|
|
64
|
-
|
65
|
-
|
66
|
-
options[:protocol] ||= match[1] unless options[:protocol] == false
|
67
|
-
options[:host] = match[2]
|
68
|
-
options[:port] = match[3] unless options.key?(:port)
|
69
|
-
end
|
59
|
+
path
|
60
|
+
end
|
70
61
|
|
71
|
-
|
72
|
-
options[:host] = normalize_host(options)
|
73
|
-
options[:port] = normalize_port(options)
|
62
|
+
private
|
74
63
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
64
|
+
def add_params(path, params)
|
65
|
+
params = { params: params } unless params.is_a?(Hash)
|
66
|
+
params.reject! { |_,v| v.to_param.nil? }
|
67
|
+
path << "?#{params.to_query}" unless params.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_anchor(path, anchor)
|
71
|
+
if anchor
|
72
|
+
path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
|
79
73
|
end
|
80
|
-
result
|
81
74
|
end
|
82
75
|
|
83
|
-
def
|
84
|
-
host
|
76
|
+
def extract_domain_from(host, tld_length)
|
77
|
+
host.split('.').last(1 + tld_length).join('.')
|
85
78
|
end
|
86
79
|
|
87
|
-
def
|
88
|
-
|
80
|
+
def extract_subdomains_from(host, tld_length)
|
81
|
+
parts = host.split('.')
|
82
|
+
parts[0..-(tld_length + 2)]
|
89
83
|
end
|
90
84
|
|
91
|
-
def
|
85
|
+
def add_trailing_slash(path)
|
86
|
+
# includes querysting
|
87
|
+
if path.include?('?')
|
88
|
+
path.sub!(/\?/, '/\&')
|
89
|
+
# does not have a .format
|
90
|
+
elsif !path.include?(".")
|
91
|
+
path.sub!(/[^\/]\z|\A\z/, '\&/')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def build_host_url(host, port, protocol, options, path)
|
96
|
+
if match = host.match(HOST_REGEXP)
|
97
|
+
protocol ||= match[1] unless protocol == false
|
98
|
+
host = match[2]
|
99
|
+
port = match[3] unless options.key? :port
|
100
|
+
end
|
101
|
+
|
102
|
+
protocol = normalize_protocol protocol
|
103
|
+
host = normalize_host(host, options)
|
104
|
+
|
105
|
+
result = protocol.dup
|
106
|
+
|
92
107
|
if options[:user] && options[:password]
|
93
|
-
"#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
94
|
-
else
|
95
|
-
""
|
108
|
+
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
96
109
|
end
|
110
|
+
|
111
|
+
result << host
|
112
|
+
normalize_port(port, protocol) { |normalized_port|
|
113
|
+
result << ":#{normalized_port}"
|
114
|
+
}
|
115
|
+
|
116
|
+
result.concat path
|
117
|
+
end
|
118
|
+
|
119
|
+
def named_host?(host)
|
120
|
+
IP_HOST_REGEXP !~ host
|
97
121
|
end
|
98
122
|
|
99
|
-
def normalize_protocol(
|
100
|
-
case
|
123
|
+
def normalize_protocol(protocol)
|
124
|
+
case protocol
|
101
125
|
when nil
|
102
126
|
"http://"
|
103
127
|
when false, "//"
|
@@ -105,36 +129,39 @@ module ActionDispatch
|
|
105
129
|
when PROTOCOL_REGEXP
|
106
130
|
"#{$1}://"
|
107
131
|
else
|
108
|
-
raise ArgumentError, "Invalid :protocol option: #{
|
132
|
+
raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
|
109
133
|
end
|
110
134
|
end
|
111
135
|
|
112
|
-
def normalize_host(options)
|
113
|
-
return
|
136
|
+
def normalize_host(_host, options)
|
137
|
+
return _host unless named_host?(_host)
|
114
138
|
|
115
139
|
tld_length = options[:tld_length] || @@tld_length
|
140
|
+
subdomain = options.fetch :subdomain, true
|
141
|
+
domain = options[:domain]
|
116
142
|
|
117
143
|
host = ""
|
118
|
-
if
|
119
|
-
|
120
|
-
|
121
|
-
host <<
|
144
|
+
if subdomain == true
|
145
|
+
return _host if domain.nil?
|
146
|
+
|
147
|
+
host << extract_subdomains_from(_host, tld_length).join('.')
|
148
|
+
elsif subdomain
|
149
|
+
host << subdomain.to_param
|
122
150
|
end
|
123
151
|
host << "." unless host.empty?
|
124
|
-
host << (
|
152
|
+
host << (domain || extract_domain_from(_host, tld_length))
|
125
153
|
host
|
126
154
|
end
|
127
155
|
|
128
|
-
def normalize_port(
|
129
|
-
return
|
156
|
+
def normalize_port(port, protocol)
|
157
|
+
return unless port
|
130
158
|
|
131
|
-
case
|
132
|
-
when "//"
|
133
|
-
nil
|
159
|
+
case protocol
|
160
|
+
when "//" then yield port
|
134
161
|
when "https://"
|
135
|
-
|
162
|
+
yield port unless port.to_i == 443
|
136
163
|
else
|
137
|
-
|
164
|
+
yield port unless port.to_i == 80
|
138
165
|
end
|
139
166
|
end
|
140
167
|
end
|
@@ -157,7 +184,7 @@ module ActionDispatch
|
|
157
184
|
|
158
185
|
# Returns the \host for this request, such as "example.com".
|
159
186
|
def raw_host_with_port
|
160
|
-
if forwarded = env["HTTP_X_FORWARDED_HOST"]
|
187
|
+
if forwarded = env["HTTP_X_FORWARDED_HOST"].presence
|
161
188
|
forwarded.split(/,\s?/).last
|
162
189
|
else
|
163
190
|
env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'action_controller/metal/exceptions'
|
2
|
+
require 'active_support/deprecation'
|
2
3
|
|
3
4
|
module ActionDispatch
|
4
5
|
module Journey
|
5
6
|
# The Formatter class is used for formatting URLs. For example, parameters
|
6
|
-
# passed to +url_for+ in
|
7
|
+
# passed to +url_for+ in Rails will eventually call Formatter#generate.
|
7
8
|
class Formatter # :nodoc:
|
8
9
|
attr_reader :routes
|
9
10
|
|
@@ -12,12 +13,12 @@ module ActionDispatch
|
|
12
13
|
@cache = nil
|
13
14
|
end
|
14
15
|
|
15
|
-
def generate(
|
16
|
-
constraints =
|
16
|
+
def generate(name, options, path_parameters, parameterize = nil)
|
17
|
+
constraints = path_parameters.merge(options)
|
17
18
|
missing_keys = []
|
18
19
|
|
19
20
|
match_route(name, constraints) do |route|
|
20
|
-
parameterized_parts = extract_parameterized_parts(route, options,
|
21
|
+
parameterized_parts = extract_parameterized_parts(route, options, path_parameters, parameterize)
|
21
22
|
|
22
23
|
# Skip this route unless a name has been provided or it is a
|
23
24
|
# standard Rails route since we can't determine whether an options
|
@@ -30,11 +31,17 @@ module ActionDispatch
|
|
30
31
|
parameterized_parts.key?(key) || route.defaults.key?(key)
|
31
32
|
end
|
32
33
|
|
34
|
+
defaults = route.defaults
|
35
|
+
required_parts = route.required_parts
|
36
|
+
parameterized_parts.delete_if do |key, value|
|
37
|
+
value.to_s == defaults[key].to_s && !required_parts.include?(key)
|
38
|
+
end
|
39
|
+
|
33
40
|
return [route.format(parameterized_parts), params]
|
34
41
|
end
|
35
42
|
|
36
|
-
message = "No route matches #{constraints.inspect}"
|
37
|
-
message << " missing required keys: #{missing_keys.inspect}"
|
43
|
+
message = "No route matches #{Hash[constraints.sort_by{|k,v| k.to_s}].inspect}"
|
44
|
+
message << " missing required keys: #{missing_keys.sort.inspect}" unless missing_keys.empty?
|
38
45
|
|
39
46
|
raise ActionController::UrlGenerationError, message
|
40
47
|
end
|
@@ -74,14 +81,28 @@ module ActionDispatch
|
|
74
81
|
if named_routes.key?(name)
|
75
82
|
yield named_routes[name]
|
76
83
|
else
|
77
|
-
|
84
|
+
# Make sure we don't show the deprecation warning more than once
|
85
|
+
warned = false
|
86
|
+
|
87
|
+
routes = non_recursive(cache, options)
|
78
88
|
|
79
89
|
hash = routes.group_by { |_, r| r.score(options) }
|
80
90
|
|
81
91
|
hash.keys.sort.reverse_each do |score|
|
82
|
-
|
92
|
+
break if score < 0
|
83
93
|
|
84
94
|
hash[score].sort_by { |i, _| i }.each do |_, route|
|
95
|
+
if name && !warned
|
96
|
+
ActiveSupport::Deprecation.warn <<-MSG.squish
|
97
|
+
You are trying to generate the URL for a named route called
|
98
|
+
#{name.inspect} but no such route was found. In the future,
|
99
|
+
this will result in an `ActionController::UrlGenerationError`
|
100
|
+
exception.
|
101
|
+
MSG
|
102
|
+
|
103
|
+
warned = true
|
104
|
+
end
|
105
|
+
|
85
106
|
yield route
|
86
107
|
end
|
87
108
|
end
|
@@ -90,14 +111,14 @@ module ActionDispatch
|
|
90
111
|
|
91
112
|
def non_recursive(cache, options)
|
92
113
|
routes = []
|
93
|
-
|
114
|
+
queue = [cache]
|
94
115
|
|
95
|
-
while
|
96
|
-
c =
|
116
|
+
while queue.any?
|
117
|
+
c = queue.shift
|
97
118
|
routes.concat(c[:___routes]) if c.key?(:___routes)
|
98
119
|
|
99
120
|
options.each do |pair|
|
100
|
-
|
121
|
+
queue << c[pair] if c.key?(pair)
|
101
122
|
end
|
102
123
|
end
|
103
124
|
|
@@ -121,14 +142,9 @@ module ActionDispatch
|
|
121
142
|
def possibles(cache, options, depth = 0)
|
122
143
|
cache.fetch(:___routes) { [] } + options.find_all { |pair|
|
123
144
|
cache.key?(pair)
|
124
|
-
}.
|
145
|
+
}.flat_map { |pair|
|
125
146
|
possibles(cache[pair], options, depth + 1)
|
126
|
-
}
|
127
|
-
end
|
128
|
-
|
129
|
-
# Returns +true+ if no missing keys are present, otherwise +false+.
|
130
|
-
def verify_required_parts!(route, parts)
|
131
|
-
missing_keys(route, parts).empty?
|
147
|
+
}
|
132
148
|
end
|
133
149
|
|
134
150
|
def build_cache
|