actionpack 4.0.13 → 4.1.0.beta1
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 +131 -1636
- data/README.rdoc +1 -6
- data/lib/abstract_controller.rb +1 -2
- data/lib/abstract_controller/base.rb +3 -25
- data/lib/abstract_controller/callbacks.rb +4 -2
- data/lib/abstract_controller/collector.rb +11 -1
- data/lib/abstract_controller/helpers.rb +18 -15
- data/lib/abstract_controller/rendering.rb +48 -127
- data/lib/action_controller.rb +1 -17
- data/lib/action_controller/base.rb +14 -6
- data/lib/action_controller/caching.rb +1 -11
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +0 -4
- data/lib/action_controller/metal/flash.rb +17 -0
- data/lib/action_controller/metal/force_ssl.rb +1 -1
- data/lib/action_controller/metal/head.rb +1 -3
- data/lib/action_controller/metal/helpers.rb +6 -2
- data/lib/action_controller/metal/http_authentication.rb +7 -14
- data/lib/action_controller/metal/instrumentation.rb +1 -1
- data/lib/action_controller/metal/live.rb +74 -0
- data/lib/action_controller/metal/mime_responds.rb +93 -16
- data/lib/action_controller/metal/params_wrapper.rb +4 -11
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +20 -20
- data/lib/action_controller/metal/renderers.rb +8 -5
- data/lib/action_controller/metal/rendering.rb +14 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +67 -13
- data/lib/action_controller/metal/responder.rb +12 -2
- data/lib/action_controller/metal/streaming.rb +18 -20
- data/lib/action_controller/metal/strong_parameters.rb +22 -34
- data/lib/action_controller/railtie.rb +0 -1
- data/lib/action_controller/test_case.rb +0 -15
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/headers.rb +1 -3
- data/lib/action_dispatch/http/mime_negotiation.rb +16 -2
- data/lib/action_dispatch/http/mime_type.rb +4 -22
- data/lib/action_dispatch/http/mime_types.rb +1 -0
- data/lib/action_dispatch/http/parameters.rb +18 -19
- data/lib/action_dispatch/http/request.rb +16 -25
- data/lib/action_dispatch/http/response.rb +21 -8
- data/lib/action_dispatch/http/upload.rb +0 -13
- data/lib/action_dispatch/http/url.rb +10 -18
- data/lib/action_dispatch/journey/formatter.rb +3 -3
- data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -5
- data/lib/action_dispatch/journey/parser.rb +1 -1
- data/lib/action_dispatch/journey/parser.y +1 -0
- data/lib/action_dispatch/journey/router.rb +7 -1
- data/lib/action_dispatch/journey/router/utils.rb +1 -1
- data/lib/action_dispatch/journey/visitors.rb +26 -47
- data/lib/action_dispatch/middleware/callbacks.rb +6 -6
- data/lib/action_dispatch/middleware/cookies.rb +15 -15
- data/lib/action_dispatch/middleware/debug_exceptions.rb +21 -13
- data/lib/action_dispatch/middleware/exception_wrapper.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +5 -11
- data/lib/action_dispatch/middleware/params_parser.rb +1 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +5 -2
- data/lib/action_dispatch/middleware/ssl.rb +1 -1
- data/lib/action_dispatch/middleware/static.rb +5 -25
- 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/{_trace.erb → _trace.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +15 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/{missing_template.erb → missing_template.html.erb} +1 -1
- 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} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/{template_error.erb → template_error.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +8 -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 +3 -3
- data/lib/action_dispatch/railtie.rb +1 -2
- data/lib/action_dispatch/request/session.rb +12 -0
- data/lib/action_dispatch/request/utils.rb +24 -0
- data/lib/action_dispatch/routing.rb +7 -6
- data/lib/action_dispatch/routing/inspector.rb +4 -4
- data/lib/action_dispatch/routing/mapper.rb +81 -138
- data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -0
- data/lib/action_dispatch/routing/redirection.rb +34 -27
- data/lib/action_dispatch/routing/route_set.rb +43 -37
- data/lib/action_dispatch/routing/url_for.rb +3 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +4 -4
- data/lib/action_dispatch/testing/integration.rb +1 -7
- data/lib/action_pack/version.rb +1 -1
- metadata +43 -167
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/deprecated.rb +0 -7
- data/lib/action_controller/deprecated/integration_test.rb +0 -5
- data/lib/action_controller/record_identifier.rb +0 -31
- data/lib/action_controller/vendor/html-scanner.rb +0 -5
- data/lib/action_view.rb +0 -93
- data/lib/action_view/base.rb +0 -205
- 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.rb +0 -58
- 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 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1087
- data/lib/action_view/helpers/debug_helper.rb +0 -39
- data/lib/action_view/helpers/form_helper.rb +0 -1882
- 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 -451
- 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.rb +0 -39
- 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 -53
- 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 -65
- 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 -22
- 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 -30
- 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/text_helper.rb +0 -448
- data/lib/action_view/helpers/translation_helper.rb +0 -112
- data/lib/action_view/helpers/url_helper.rb +0 -635
- 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 -248
- 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 -500
- 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.rb +0 -339
- data/lib/action_view/template/error.rb +0 -138
- data/lib/action_view/template/handlers.rb +0 -53
- 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/resolver.rb +0 -340
- data/lib/action_view/template/text.rb +0 -34
- data/lib/action_view/template/types.rb +0 -57
- 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.rb +0 -20
- 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
@@ -1,9 +1,10 @@
|
|
1
|
+
require 'action_view'
|
1
2
|
require "action_controller/log_subscriber"
|
2
3
|
require "action_controller/metal/params_wrapper"
|
3
4
|
|
4
5
|
module ActionController
|
5
6
|
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
|
6
|
-
# on request and then either
|
7
|
+
# on request and then either it renders a template or redirects to another action. An action is defined as a public method
|
7
8
|
# on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
|
8
9
|
#
|
9
10
|
# By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
|
@@ -200,7 +201,7 @@ module ActionController
|
|
200
201
|
end
|
201
202
|
|
202
203
|
MODULES = [
|
203
|
-
AbstractController::
|
204
|
+
AbstractController::Rendering,
|
204
205
|
AbstractController::Translation,
|
205
206
|
AbstractController::AssetPaths,
|
206
207
|
|
@@ -208,6 +209,7 @@ module ActionController
|
|
208
209
|
HideActions,
|
209
210
|
UrlFor,
|
210
211
|
Redirecting,
|
212
|
+
ActionView::Layouts,
|
211
213
|
Rendering,
|
212
214
|
Renderers::All,
|
213
215
|
ConditionalGet,
|
@@ -223,7 +225,6 @@ module ActionController
|
|
223
225
|
ForceSSL,
|
224
226
|
Streaming,
|
225
227
|
DataStreaming,
|
226
|
-
RecordIdentifier,
|
227
228
|
HttpAuthentication::Basic::ControllerMethods,
|
228
229
|
HttpAuthentication::Digest::ControllerMethods,
|
229
230
|
HttpAuthentication::Token::ControllerMethods,
|
@@ -249,10 +250,17 @@ module ActionController
|
|
249
250
|
end
|
250
251
|
|
251
252
|
# Define some internal variables that should not be propagated to the view.
|
252
|
-
|
253
|
+
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [
|
253
254
|
:@_status, :@_headers, :@_params, :@_env, :@_response, :@_request,
|
254
|
-
:@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout
|
255
|
-
|
255
|
+
:@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout ]
|
256
|
+
|
257
|
+
def _protected_ivars # :nodoc:
|
258
|
+
PROTECTED_IVARS
|
259
|
+
end
|
260
|
+
|
261
|
+
def self.protected_instance_variables
|
262
|
+
PROTECTED_IVARS
|
263
|
+
end
|
256
264
|
|
257
265
|
ActiveSupport.run_load_hooks(:action_controller, self)
|
258
266
|
end
|
@@ -9,7 +9,7 @@ module ActionController
|
|
9
9
|
# You can read more about each approach by clicking the modules below.
|
10
10
|
#
|
11
11
|
# Note: To turn off all caching, set
|
12
|
-
# config.action_controller.perform_caching = false
|
12
|
+
# config.action_controller.perform_caching = false
|
13
13
|
#
|
14
14
|
# == \Caching stores
|
15
15
|
#
|
@@ -58,16 +58,6 @@ module ActionController
|
|
58
58
|
config_accessor :default_static_extension
|
59
59
|
self.default_static_extension ||= '.html'
|
60
60
|
|
61
|
-
def self.page_cache_extension=(extension)
|
62
|
-
ActiveSupport::Deprecation.deprecation_warning(:page_cache_extension, :default_static_extension)
|
63
|
-
self.default_static_extension = extension
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.page_cache_extension
|
67
|
-
ActiveSupport::Deprecation.deprecation_warning(:page_cache_extension, :default_static_extension)
|
68
|
-
default_static_extension
|
69
|
-
end
|
70
|
-
|
71
61
|
config_accessor :perform_caching
|
72
62
|
self.perform_caching = true if perform_caching.nil?
|
73
63
|
|
@@ -33,7 +33,7 @@ module ActionController
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def halted_callback(event)
|
36
|
-
info("Filter chain halted as #{event.payload[:filter]} rendered or redirected")
|
36
|
+
info("Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected")
|
37
37
|
end
|
38
38
|
|
39
39
|
def send_file(event)
|
@@ -11,6 +11,23 @@ module ActionController #:nodoc:
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
14
|
+
# Creates new flash types. You can pass as many types as you want to create
|
15
|
+
# flash types other than the default <tt>alert</tt> and <tt>notice</tt> in
|
16
|
+
# your controllers and views. For instance:
|
17
|
+
#
|
18
|
+
# # in application_controller.rb
|
19
|
+
# class ApplicationController < ActionController::Base
|
20
|
+
# add_flash_types :warning
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # in your controller
|
24
|
+
# redirect_to user_path(@user), warning: "Incomplete profile"
|
25
|
+
#
|
26
|
+
# # in your view
|
27
|
+
# <%= warning %>
|
28
|
+
#
|
29
|
+
# This method will automatically define a new method for each of the given
|
30
|
+
# names, and it will be available in your views.
|
14
31
|
def add_flash_types(*types)
|
15
32
|
types.each do |type|
|
16
33
|
next if _flash_types.include?(type)
|
@@ -48,7 +48,7 @@ module ActionController
|
|
48
48
|
# You can pass any of the following options to affect the redirect status and response
|
49
49
|
# * <tt>status</tt> - Redirect with a custom status (default is 301 Moved Permanently)
|
50
50
|
# * <tt>flash</tt> - Set a flash message when redirecting
|
51
|
-
# * <tt>alert</tt> - Set
|
51
|
+
# * <tt>alert</tt> - Set an alert message when redirecting
|
52
52
|
# * <tt>notice</tt> - Set a notice message when redirecting
|
53
53
|
#
|
54
54
|
# ==== Action Options
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module ActionController
|
2
2
|
module Head
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
3
|
# Return a response that has no content (merely headers). The options
|
6
4
|
# argument is interpreted to be a hash of header names and values.
|
7
5
|
# This allows you to easily return a response that consists only of
|
@@ -29,7 +27,7 @@ module ActionController
|
|
29
27
|
self.status = status
|
30
28
|
self.location = url_for(location) if location
|
31
29
|
|
32
|
-
if include_content?(self.
|
30
|
+
if include_content?(self.status)
|
33
31
|
self.content_type = content_type || (Mime[formats.first] if formats)
|
34
32
|
self.response.charset = false if self.response
|
35
33
|
self.response_body = " "
|
@@ -5,7 +5,7 @@ module ActionController
|
|
5
5
|
#
|
6
6
|
# In addition to using the standard template helpers provided, creating custom helpers to
|
7
7
|
# extract complicated logic or reusable functionality is strongly encouraged. By default, each controller
|
8
|
-
# will include all helpers.
|
8
|
+
# will include all helpers. These helpers are only accessible on the controller through <tt>.helpers</tt>
|
9
9
|
#
|
10
10
|
# In previous versions of \Rails the controller will include a helper whose
|
11
11
|
# name matches that of the controller, e.g., <tt>MyController</tt> will automatically
|
@@ -73,7 +73,11 @@ module ActionController
|
|
73
73
|
|
74
74
|
# Provides a proxy to access helpers methods from outside the view.
|
75
75
|
def helpers
|
76
|
-
@helper_proxy ||=
|
76
|
+
@helper_proxy ||= begin
|
77
|
+
proxy = ActionView::Base.new
|
78
|
+
proxy.config = config.inheritable_copy
|
79
|
+
proxy.extend(_helpers)
|
80
|
+
end
|
77
81
|
end
|
78
82
|
|
79
83
|
# Overwrite modules_for_helpers to accept :all as argument, which loads
|
@@ -96,7 +96,7 @@ module ActionController
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def user_name_and_password(request)
|
99
|
-
decode_credentials(request).split(
|
99
|
+
decode_credentials(request).split(/:/, 2)
|
100
100
|
end
|
101
101
|
|
102
102
|
def decode_credentials(request)
|
@@ -109,8 +109,8 @@ module ActionController
|
|
109
109
|
|
110
110
|
def authentication_request(controller, realm)
|
111
111
|
controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.gsub(/"/, "")}")
|
112
|
-
controller.status = 401
|
113
112
|
controller.response_body = "HTTP Basic: Access denied.\n"
|
113
|
+
controller.status = 401
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -244,8 +244,8 @@ module ActionController
|
|
244
244
|
def authentication_request(controller, realm, message = nil)
|
245
245
|
message ||= "HTTP Digest: Access denied.\n"
|
246
246
|
authentication_header(controller, realm)
|
247
|
-
controller.status = 401
|
248
247
|
controller.response_body = message
|
248
|
+
controller.status = 401
|
249
249
|
end
|
250
250
|
|
251
251
|
def secret_token(request)
|
@@ -385,7 +385,6 @@ module ActionController
|
|
385
385
|
#
|
386
386
|
# RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
|
387
387
|
module Token
|
388
|
-
TOKEN_KEY = 'token='
|
389
388
|
TOKEN_REGEX = /^Token /
|
390
389
|
AUTHN_PAIR_DELIMITERS = /(?:,|;|\t+)/
|
391
390
|
extend self
|
@@ -438,7 +437,7 @@ module ActionController
|
|
438
437
|
authorization_request = request.authorization.to_s
|
439
438
|
if authorization_request[TOKEN_REGEX]
|
440
439
|
params = token_params_from authorization_request
|
441
|
-
[params.shift
|
440
|
+
[params.shift.last, Hash[params].with_indifferent_access]
|
442
441
|
end
|
443
442
|
end
|
444
443
|
|
@@ -453,20 +452,14 @@ module ActionController
|
|
453
452
|
|
454
453
|
# This removes the `"` characters wrapping the value.
|
455
454
|
def rewrite_param_values(array_params)
|
456
|
-
array_params.each { |param|
|
455
|
+
array_params.each { |param| param.last.gsub! %r/^"|"$/, '' }
|
457
456
|
end
|
458
457
|
|
459
458
|
# This method takes an authorization body and splits up the key-value
|
460
459
|
# pairs by the standardized `:`, `;`, or `\t` delimiters defined in
|
461
460
|
# `AUTHN_PAIR_DELIMITERS`.
|
462
461
|
def raw_params(auth)
|
463
|
-
|
464
|
-
|
465
|
-
if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
|
466
|
-
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
|
467
|
-
end
|
468
|
-
|
469
|
-
_raw_params
|
462
|
+
auth.sub(TOKEN_REGEX, '').split(/"\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
|
470
463
|
end
|
471
464
|
|
472
465
|
# Encodes the given token and options into an Authorization header value.
|
@@ -476,7 +469,7 @@ module ActionController
|
|
476
469
|
#
|
477
470
|
# Returns String.
|
478
471
|
def encode_credentials(token, options = {})
|
479
|
-
values = ["
|
472
|
+
values = ["token=#{token.to_s.inspect}"] + options.map do |key, value|
|
480
473
|
"#{key}=#{value.to_s.inspect}"
|
481
474
|
end
|
482
475
|
"Token #{values * ", "}"
|
@@ -67,7 +67,7 @@ module ActionController
|
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
-
# A hook invoked
|
70
|
+
# A hook invoked every time a before callback is halted.
|
71
71
|
def halted_callback_hook(filter)
|
72
72
|
ActiveSupport::Notifications.instrument("halted_callback.action_controller", :filter => filter)
|
73
73
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'action_dispatch/http/response'
|
2
2
|
require 'delegate'
|
3
|
+
require 'active_support/json'
|
3
4
|
|
4
5
|
module ActionController
|
5
6
|
# Mix this module in to your controller, and all actions in that controller
|
@@ -32,6 +33,79 @@ module ActionController
|
|
32
33
|
# the main thread. Make sure your actions are thread safe, and this shouldn't
|
33
34
|
# be a problem (don't share state across threads, etc).
|
34
35
|
module Live
|
36
|
+
# This class provides the ability to write an SSE (Server Sent Event)
|
37
|
+
# to an IO stream. The class is initialized with a stream and can be used
|
38
|
+
# to either write a JSON string or an object which can be converted to JSON.
|
39
|
+
#
|
40
|
+
# Writing an object will convert it into standard SSE format with whatever
|
41
|
+
# options you have configured. You may choose to set the following options:
|
42
|
+
#
|
43
|
+
# 1) Event. If specified, an event with this name will be dispatched on
|
44
|
+
# the browser.
|
45
|
+
# 2) Retry. The reconnection time in milliseconds used when attempting
|
46
|
+
# to send the event.
|
47
|
+
# 3) Id. If the connection dies while sending an SSE to the browser, then
|
48
|
+
# the server will receive a +Last-Event-ID+ header with value equal to +id+.
|
49
|
+
#
|
50
|
+
# After setting an option in the constructor of the SSE object, all future
|
51
|
+
# SSEs sent across the stream will use those options unless overridden.
|
52
|
+
#
|
53
|
+
# Example Usage:
|
54
|
+
#
|
55
|
+
# class MyController < ActionController::Base
|
56
|
+
# include ActionController::Live
|
57
|
+
#
|
58
|
+
# def index
|
59
|
+
# response.headers['Content-Type'] = 'text/event-stream'
|
60
|
+
# sse = SSE.new(response.stream, retry: 300, event: "event-name")
|
61
|
+
# sse.write({ name: 'John'})
|
62
|
+
# sse.write({ name: 'John'}, id: 10)
|
63
|
+
# sse.write({ name: 'John'}, id: 10, event: "other-event")
|
64
|
+
# sse.write({ name: 'John'}, id: 10, event: "other-event", retry: 500)
|
65
|
+
# ensure
|
66
|
+
# sse.close
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# Note: SSEs are not currently supported by IE. However, they are supported
|
71
|
+
# by Chrome, Firefox, Opera, and Safari.
|
72
|
+
class SSE
|
73
|
+
|
74
|
+
WHITELISTED_OPTIONS = %w( retry event id )
|
75
|
+
|
76
|
+
def initialize(stream, options = {})
|
77
|
+
@stream = stream
|
78
|
+
@options = options
|
79
|
+
end
|
80
|
+
|
81
|
+
def close
|
82
|
+
@stream.close
|
83
|
+
end
|
84
|
+
|
85
|
+
def write(object, options = {})
|
86
|
+
case object
|
87
|
+
when String
|
88
|
+
perform_write(object, options)
|
89
|
+
else
|
90
|
+
perform_write(ActiveSupport::JSON.encode(object), options)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def perform_write(json, options)
|
97
|
+
current_options = @options.merge(options).stringify_keys
|
98
|
+
|
99
|
+
WHITELISTED_OPTIONS.each do |option_name|
|
100
|
+
if (option_value = current_options[option_name])
|
101
|
+
@stream.write "#{option_name}: #{option_value}\n"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
@stream.write "data: #{json}\n\n"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
35
109
|
class Buffer < ActionDispatch::Response::Buffer #:nodoc:
|
36
110
|
def initialize(response)
|
37
111
|
@error_callback = nil
|
@@ -181,13 +181,50 @@ module ActionController #:nodoc:
|
|
181
181
|
# end
|
182
182
|
# end
|
183
183
|
#
|
184
|
+
# Formats can have different variants.
|
185
|
+
#
|
186
|
+
# The request variant is a specialization of the request format, like <tt>:tablet</tt>,
|
187
|
+
# <tt>:phone</tt>, or <tt>:desktop</tt>.
|
188
|
+
#
|
189
|
+
# We often want to render different html/json/xml templates for phones,
|
190
|
+
# tablets, and desktop browsers. Variants make it easy.
|
191
|
+
#
|
192
|
+
# You can set the variant in a +before_action+:
|
193
|
+
#
|
194
|
+
# request.variant = :tablet if request.user_agent =~ /iPad/
|
195
|
+
#
|
196
|
+
# Respond to variants in the action just like you respond to formats:
|
197
|
+
#
|
198
|
+
# respond_to do |format|
|
199
|
+
# format.html do |variant|
|
200
|
+
# variant.tablet # renders app/views/projects/show.html+tablet.erb
|
201
|
+
# variant.phone { extra_setup; render ... }
|
202
|
+
# variant.none { special_setup } # executed only if there is no variant set
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# Provide separate templates for each format and variant:
|
207
|
+
#
|
208
|
+
# app/views/projects/show.html.erb
|
209
|
+
# app/views/projects/show.html+tablet.erb
|
210
|
+
# app/views/projects/show.html+phone.erb
|
211
|
+
#
|
212
|
+
# When you're not sharing any code within the format, you can simplify defining variants
|
213
|
+
# using the inline syntax:
|
214
|
+
#
|
215
|
+
# respond_to do |format|
|
216
|
+
# format.js { render "trash" }
|
217
|
+
# format.html.phone { redirect_to progress_path }
|
218
|
+
# format.html.none { render "trash" }
|
219
|
+
# end
|
220
|
+
#
|
184
221
|
# Be sure to check the documentation of +respond_with+ and
|
185
222
|
# <tt>ActionController::MimeResponds.respond_to</tt> for more examples.
|
186
223
|
def respond_to(*mimes, &block)
|
187
224
|
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
|
188
225
|
|
189
226
|
if collector = retrieve_collector_from_mimes(mimes, &block)
|
190
|
-
response = collector.response
|
227
|
+
response = collector.response(request.variant)
|
191
228
|
response ? response.call : render({})
|
192
229
|
end
|
193
230
|
end
|
@@ -260,7 +297,7 @@ module ActionController #:nodoc:
|
|
260
297
|
# * for other requests - i.e. data formats such as xml, json, csv etc, if
|
261
298
|
# the resource passed to +respond_with+ responds to <code>to_<format></code>,
|
262
299
|
# the method attempts to render the resource in the requested format
|
263
|
-
# directly, e.g. for an xml request, the response is equivalent to calling
|
300
|
+
# directly, e.g. for an xml request, the response is equivalent to calling
|
264
301
|
# <code>render xml: resource</code>.
|
265
302
|
#
|
266
303
|
# === Nested resources
|
@@ -321,12 +358,15 @@ module ActionController #:nodoc:
|
|
321
358
|
# 2. <tt>:action</tt> - overwrites the default render action used after an
|
322
359
|
# unsuccessful html +post+ request.
|
323
360
|
def respond_with(*resources, &block)
|
324
|
-
|
325
|
-
|
361
|
+
if self.class.mimes_for_respond_to.empty?
|
362
|
+
raise "In order to use respond_with, first you need to declare the " \
|
363
|
+
"formats your controller responds to in the class level."
|
364
|
+
end
|
326
365
|
|
327
366
|
if collector = retrieve_collector_from_mimes(&block)
|
328
367
|
options = resources.size == 1 ? {} : resources.extract_options!
|
329
|
-
options
|
368
|
+
options = options.clone
|
369
|
+
options[:default_response] = collector.response(request.variant)
|
330
370
|
(options.delete(:responder) || self.class.responder).call(self, resources, options)
|
331
371
|
end
|
332
372
|
end
|
@@ -364,9 +404,7 @@ module ActionController #:nodoc:
|
|
364
404
|
format = collector.negotiate_format(request)
|
365
405
|
|
366
406
|
if format
|
367
|
-
|
368
|
-
lookup_context.formats = [format.to_sym]
|
369
|
-
lookup_context.rendered_format = lookup_context.formats.first
|
407
|
+
_process_format(format)
|
370
408
|
collector
|
371
409
|
else
|
372
410
|
raise ActionController::UnknownFormat
|
@@ -397,11 +435,12 @@ module ActionController #:nodoc:
|
|
397
435
|
# request, with this response then being accessible by calling #response.
|
398
436
|
class Collector
|
399
437
|
include AbstractController::Collector
|
400
|
-
attr_accessor :
|
438
|
+
attr_accessor :format
|
401
439
|
|
402
440
|
def initialize(mimes)
|
403
|
-
@
|
404
|
-
|
441
|
+
@responses = {}
|
442
|
+
|
443
|
+
mimes.each { |mime| @responses["Mime::#{mime.upcase}".constantize] = nil }
|
405
444
|
end
|
406
445
|
|
407
446
|
def any(*args, &block)
|
@@ -415,16 +454,54 @@ module ActionController #:nodoc:
|
|
415
454
|
|
416
455
|
def custom(mime_type, &block)
|
417
456
|
mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
|
418
|
-
@
|
419
|
-
|
457
|
+
@responses[mime_type] ||= if block_given?
|
458
|
+
block
|
459
|
+
else
|
460
|
+
VariantCollector.new
|
461
|
+
end
|
420
462
|
end
|
421
463
|
|
422
|
-
def response
|
423
|
-
@responses.fetch(format, @responses[Mime::ALL])
|
464
|
+
def response(variant)
|
465
|
+
response = @responses.fetch(format, @responses[Mime::ALL])
|
466
|
+
if response.is_a?(VariantCollector)
|
467
|
+
response.variant(variant)
|
468
|
+
elsif response.nil? || response.arity == 0
|
469
|
+
response
|
470
|
+
else
|
471
|
+
lambda { response.call VariantFilter.new(variant) }
|
472
|
+
end
|
424
473
|
end
|
425
474
|
|
426
475
|
def negotiate_format(request)
|
427
|
-
@format = request.negotiate_mime(
|
476
|
+
@format = request.negotiate_mime(@responses.keys)
|
477
|
+
end
|
478
|
+
|
479
|
+
#Used for inline syntax
|
480
|
+
class VariantCollector #:nodoc:
|
481
|
+
def initialize
|
482
|
+
@variants = {}
|
483
|
+
end
|
484
|
+
|
485
|
+
def method_missing(name, *args, &block)
|
486
|
+
@variants[name] = block if block_given?
|
487
|
+
end
|
488
|
+
|
489
|
+
def variant(name)
|
490
|
+
@variants[name.nil? ? :none : name]
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
#Used for nested block syntax
|
495
|
+
class VariantFilter #:nodoc:
|
496
|
+
def initialize(variant)
|
497
|
+
@variant = variant
|
498
|
+
end
|
499
|
+
|
500
|
+
def method_missing(name)
|
501
|
+
if block_given?
|
502
|
+
yield if name == @variant || (name == :none && @variant.nil?)
|
503
|
+
end
|
504
|
+
end
|
428
505
|
end
|
429
506
|
end
|
430
507
|
end
|