actionpack 4.2.10 → 7.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,35 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
module ActionController # :nodoc:
|
6
|
+
# # Action Controller Rescue
|
7
|
+
#
|
8
|
+
# This module is responsible for providing
|
9
|
+
# [rescue_from](rdoc-ref:ActiveSupport::Rescuable::ClassMethods#rescue_from) to
|
10
|
+
# controllers, wrapping actions to handle configured errors, and configuring
|
11
|
+
# when detailed exceptions must be shown.
|
5
12
|
module Rescue
|
6
13
|
extend ActiveSupport::Concern
|
7
14
|
include ActiveSupport::Rescuable
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
super(exception)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Override this method if you want to customize when detailed
|
19
|
-
# exceptions must be shown. This method is only called when
|
20
|
-
# consider_all_requests_local is false. By default, it returns
|
21
|
-
# false, but someone may set it to `request.local?` so local
|
22
|
-
# requests in production still shows the detailed exception pages.
|
16
|
+
# Override this method if you want to customize when detailed exceptions must be
|
17
|
+
# shown. This method is only called when `consider_all_requests_local` is
|
18
|
+
# `false`. By default, it returns `false`, but someone may set it to
|
19
|
+
# `request.local?` so local requests in production still show the detailed
|
20
|
+
# exception pages.
|
23
21
|
def show_detailed_exceptions?
|
24
22
|
false
|
25
23
|
end
|
26
24
|
|
27
25
|
private
|
28
|
-
def process_action(*
|
26
|
+
def process_action(*)
|
29
27
|
super
|
30
28
|
rescue Exception => exception
|
31
|
-
request.env[
|
32
|
-
rescue_with_handler(exception) || raise
|
29
|
+
request.env["action_dispatch.show_detailed_exceptions"] ||= show_detailed_exceptions?
|
30
|
+
rescue_with_handler(exception) || raise
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
@@ -1,205 +1,246 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
module ActionController # :nodoc:
|
6
|
+
# # Action Controller Streaming
|
7
|
+
#
|
4
8
|
# Allows views to be streamed back to the client as they are rendered.
|
5
9
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
10
|
+
# By default, Rails renders views by first rendering the template and then the
|
11
|
+
# layout. The response is sent to the client after the whole template is
|
12
|
+
# rendered, all queries are made, and the layout is processed.
|
9
13
|
#
|
10
14
|
# Streaming inverts the rendering flow by rendering the layout first and
|
11
|
-
#
|
12
|
-
# header of the HTML (which is usually in the layout) to be streamed back
|
13
|
-
#
|
14
|
-
#
|
15
|
+
# subsequently each part of the layout as they are processed. This allows the
|
16
|
+
# header of the HTML (which is usually in the layout) to be streamed back to
|
17
|
+
# client very quickly, enabling JavaScripts and stylesheets to be loaded earlier
|
18
|
+
# than usual.
|
19
|
+
#
|
20
|
+
# Several Rack middlewares may not work and you need to be careful when
|
21
|
+
# streaming. This is covered in more detail below, see the Streaming@Middlewares
|
22
|
+
# section.
|
23
|
+
#
|
24
|
+
# Streaming can be added to a given template easily, all you need to do is to
|
25
|
+
# pass the `:stream` option to `render`.
|
26
|
+
#
|
27
|
+
# class PostsController
|
28
|
+
# def index
|
29
|
+
# @posts = Post.all
|
30
|
+
# render stream: true
|
31
|
+
# end
|
32
|
+
# end
|
15
33
|
#
|
16
|
-
#
|
17
|
-
# Rack middlewares may not work and you need to be careful when streaming.
|
18
|
-
# Those points are going to be addressed soon.
|
34
|
+
# ## When to use streaming
|
19
35
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
36
|
+
# Streaming may be considered to be overkill for lightweight actions like `new`
|
37
|
+
# or `edit`. The real benefit of streaming is on expensive actions that, for
|
38
|
+
# example, do a lot of queries on the database.
|
23
39
|
#
|
24
|
-
#
|
25
|
-
#
|
40
|
+
# In such actions, you want to delay queries execution as much as you can. For
|
41
|
+
# example, imagine the following `dashboard` action:
|
26
42
|
#
|
27
|
-
#
|
28
|
-
# def index
|
43
|
+
# def dashboard
|
29
44
|
# @posts = Post.all
|
30
|
-
#
|
45
|
+
# @pages = Page.all
|
46
|
+
# @articles = Article.all
|
31
47
|
# end
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# == When to use streaming
|
35
|
-
#
|
36
|
-
# Streaming may be considered to be overkill for lightweight actions like
|
37
|
-
# +new+ or +edit+. The real benefit of streaming is on expensive actions
|
38
|
-
# that, for example, do a lot of queries on the database.
|
39
|
-
#
|
40
|
-
# In such actions, you want to delay queries execution as much as you can.
|
41
|
-
# For example, imagine the following +dashboard+ action:
|
42
|
-
#
|
43
|
-
# def dashboard
|
44
|
-
# @posts = Post.all
|
45
|
-
# @pages = Page.all
|
46
|
-
# @articles = Article.all
|
47
|
-
# end
|
48
48
|
#
|
49
49
|
# Most of the queries here are happening in the controller. In order to benefit
|
50
50
|
# from streaming you would want to rewrite it as:
|
51
51
|
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
52
|
+
# def dashboard
|
53
|
+
# # Allow lazy execution of the queries
|
54
|
+
# @posts = Post.all
|
55
|
+
# @pages = Page.all
|
56
|
+
# @articles = Article.all
|
57
|
+
# render stream: true
|
58
|
+
# end
|
59
59
|
#
|
60
|
-
# Notice that
|
61
|
-
#
|
60
|
+
# Notice that `:stream` only works with templates. Rendering `:json` or `:xml`
|
61
|
+
# with `:stream` won't work.
|
62
62
|
#
|
63
|
-
#
|
63
|
+
# ## Communication between layout and template
|
64
64
|
#
|
65
|
-
# When streaming, rendering happens top-down instead of inside-out.
|
66
|
-
#
|
67
|
-
#
|
65
|
+
# When streaming, rendering happens top-down instead of inside-out. Rails starts
|
66
|
+
# with the layout, and the template is rendered later, when its `yield` is
|
67
|
+
# reached.
|
68
68
|
#
|
69
|
-
# This means that, if your application currently relies on instance
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
69
|
+
# This means that, if your application currently relies on instance variables
|
70
|
+
# set in the template to be used in the layout, they won't work once you move to
|
71
|
+
# streaming. The proper way to communicate between layout and template,
|
72
|
+
# regardless of whether you use streaming or not, is by using `content_for`,
|
73
|
+
# `provide`, and `yield`.
|
74
74
|
#
|
75
|
-
# Take a simple example where the layout expects the template to tell
|
76
|
-
#
|
75
|
+
# Take a simple example where the layout expects the template to tell which
|
76
|
+
# title to use:
|
77
77
|
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
78
|
+
# <html>
|
79
|
+
# <head><title><%= yield :title %></title></head>
|
80
|
+
# <body><%= yield %></body>
|
81
|
+
# </html>
|
82
82
|
#
|
83
|
-
# You would use
|
83
|
+
# You would use `content_for` in your template to specify the title:
|
84
84
|
#
|
85
|
-
#
|
86
|
-
#
|
85
|
+
# <%= content_for :title, "Main" %>
|
86
|
+
# Hello
|
87
87
|
#
|
88
88
|
# And the final result would be:
|
89
89
|
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
90
|
+
# <html>
|
91
|
+
# <head><title>Main</title></head>
|
92
|
+
# <body>Hello</body>
|
93
|
+
# </html>
|
94
94
|
#
|
95
|
-
# However, if
|
96
|
-
#
|
97
|
-
# template:
|
95
|
+
# However, if `content_for` is called several times, the final result would have
|
96
|
+
# all calls concatenated. For instance, if we have the following template:
|
98
97
|
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
98
|
+
# <%= content_for :title, "Main" %>
|
99
|
+
# Hello
|
100
|
+
# <%= content_for :title, " page" %>
|
102
101
|
#
|
103
102
|
# The final result would be:
|
104
103
|
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
104
|
+
# <html>
|
105
|
+
# <head><title>Main page</title></head>
|
106
|
+
# <body>Hello</body>
|
107
|
+
# </html>
|
108
|
+
#
|
109
|
+
# This means that, if you have `yield :title` in your layout and you want to use
|
110
|
+
# streaming, you would have to render the whole template (and eventually trigger
|
111
|
+
# all queries) before streaming the title and all assets, which defeats the
|
112
|
+
# purpose of streaming. Alternatively, you can use a helper called `provide`
|
113
|
+
# that does the same as `content_for` but tells the layout to stop searching for
|
114
|
+
# other entries and continue rendering.
|
109
115
|
#
|
110
|
-
#
|
111
|
-
# and you want to use streaming, you would have to render the whole template
|
112
|
-
# (and eventually trigger all queries) before streaming the title and all
|
113
|
-
# assets, which kills the purpose of streaming. For this reason Rails 3.1
|
114
|
-
# introduces a new helper called +provide+ that does the same as +content_for+
|
115
|
-
# but tells the layout to stop searching for other entries and continue rendering.
|
116
|
+
# For instance, the template above using `provide` would be:
|
116
117
|
#
|
117
|
-
#
|
118
|
+
# <%= provide :title, "Main" %>
|
119
|
+
# Hello
|
120
|
+
# <%= content_for :title, " page" %>
|
118
121
|
#
|
119
|
-
#
|
120
|
-
# Hello
|
121
|
-
# <%= content_for :title, " page" %>
|
122
|
+
# Resulting in:
|
122
123
|
#
|
123
|
-
#
|
124
|
+
# <html>
|
125
|
+
# <head><title>Main</title></head>
|
126
|
+
# <body>Hello</body>
|
127
|
+
# </html>
|
124
128
|
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
# <body>Hello</body>
|
128
|
-
# </html>
|
129
|
+
# That said, when streaming, you need to properly check your templates and
|
130
|
+
# choose when to use `provide` and `content_for`.
|
129
131
|
#
|
130
|
-
#
|
131
|
-
# and choose when to use +provide+ and +content_for+.
|
132
|
+
# See also ActionView::Helpers::CaptureHelper for more information.
|
132
133
|
#
|
133
|
-
#
|
134
|
+
# ## Headers, cookies, session, and flash
|
134
135
|
#
|
135
|
-
# When streaming, the HTTP headers are sent to the client right before
|
136
|
-
#
|
137
|
-
#
|
138
|
-
# to the client.
|
136
|
+
# When streaming, the HTTP headers are sent to the client right before it
|
137
|
+
# renders the first line. This means that, modifying headers, cookies, session
|
138
|
+
# or flash after the template starts rendering will not propagate to the client.
|
139
139
|
#
|
140
|
-
#
|
140
|
+
# ## Middlewares
|
141
141
|
#
|
142
|
-
# Middlewares that need to manipulate the body won't work with streaming.
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
142
|
+
# Middlewares that need to manipulate the body won't work with streaming. You
|
143
|
+
# should disable those middlewares whenever streaming in development or
|
144
|
+
# production. For instance, `Rack::Bug` won't work when streaming as it needs to
|
145
|
+
# inject contents in the HTML body.
|
146
146
|
#
|
147
|
-
# Also
|
148
|
-
#
|
149
|
-
#
|
147
|
+
# Also `Rack::Cache` won't work with streaming as it does not support streaming
|
148
|
+
# bodies yet. Whenever streaming `Cache-Control` is automatically set to
|
149
|
+
# "no-cache".
|
150
150
|
#
|
151
|
-
#
|
151
|
+
# ## Errors
|
152
152
|
#
|
153
153
|
# When it comes to streaming, exceptions get a bit more complicated. This
|
154
|
-
# happens because part of the template was already rendered and streamed to
|
155
|
-
#
|
154
|
+
# happens because part of the template was already rendered and streamed to the
|
155
|
+
# client, making it impossible to render a whole exception page.
|
156
156
|
#
|
157
|
-
# Currently, when an exception happens in development or production, Rails
|
158
|
-
#
|
157
|
+
# Currently, when an exception happens in development or production, Rails will
|
158
|
+
# automatically stream to the client:
|
159
159
|
#
|
160
|
-
#
|
160
|
+
# "><script>window.location = "/500.html"</script></html>
|
161
161
|
#
|
162
|
-
# The first two characters ("
|
163
|
-
# while rendering attributes for a given tag. You can check the real cause
|
164
|
-
#
|
162
|
+
# The first two characters (`">`) are required in case the exception happens
|
163
|
+
# while rendering attributes for a given tag. You can check the real cause for
|
164
|
+
# the exception in your logger.
|
165
165
|
#
|
166
|
-
#
|
166
|
+
# ## Web server support
|
167
167
|
#
|
168
|
-
# Not all web servers support streaming out-of-the-box. You need to check
|
169
|
-
#
|
168
|
+
# Not all web servers support streaming out-of-the-box. You need to check the
|
169
|
+
# instructions for each of them.
|
170
170
|
#
|
171
|
-
#
|
171
|
+
# #### Unicorn
|
172
172
|
#
|
173
|
-
# Unicorn supports streaming but it needs to be configured. For this, you
|
174
|
-
#
|
173
|
+
# Unicorn supports streaming but it needs to be configured. For this, you need
|
174
|
+
# to create a config file as follow:
|
175
175
|
#
|
176
|
-
#
|
177
|
-
#
|
176
|
+
# # unicorn.config.rb
|
177
|
+
# listen 3000, tcp_nopush: false
|
178
178
|
#
|
179
179
|
# And use it on initialization:
|
180
180
|
#
|
181
|
-
#
|
181
|
+
# unicorn_rails --config-file unicorn.config.rb
|
182
182
|
#
|
183
|
-
# You may also want to configure other parameters like
|
184
|
-
# Please check its documentation for more information: http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen
|
183
|
+
# You may also want to configure other parameters like `:tcp_nodelay`.
|
185
184
|
#
|
186
|
-
#
|
187
|
-
#
|
185
|
+
# For more information, please check the
|
186
|
+
# [documentation](https://bogomips.org/unicorn/Unicorn/Configurator.html#method-
|
187
|
+
# i-listen).
|
188
188
|
#
|
189
|
-
#
|
189
|
+
# If you are using Unicorn with NGINX, you may need to tweak NGINX. Streaming
|
190
|
+
# should work out of the box on Rainbows.
|
190
191
|
#
|
191
|
-
#
|
192
|
+
# #### Passenger
|
192
193
|
#
|
194
|
+
# Phusion Passenger with NGINX, offers two streaming mechanisms out of the box.
|
195
|
+
#
|
196
|
+
# 1. NGINX response buffering mechanism which is dependent on the value of
|
197
|
+
# `passenger_buffer_response` option (default is "off").
|
198
|
+
# 2. Passenger buffering system which is always 'on' irrespective of the value
|
199
|
+
# of `passenger_buffer_response`.
|
200
|
+
#
|
201
|
+
#
|
202
|
+
# When `passenger_buffer_response` is turned "on", then streaming would be done
|
203
|
+
# at the NGINX level which waits until the application is done sending the
|
204
|
+
# response back to the client.
|
205
|
+
#
|
206
|
+
# For more information, please check the [documentation]
|
207
|
+
# (https://www.phusionpassenger.com/docs/references/config_reference/nginx/#passenger_buffer_response).
|
193
208
|
module Streaming
|
194
|
-
|
209
|
+
class Body # :nodoc:
|
210
|
+
TERM = "\r\n"
|
211
|
+
TAIL = "0#{TERM}"
|
212
|
+
|
213
|
+
# Store the response body to be chunked.
|
214
|
+
def initialize(body)
|
215
|
+
@body = body
|
216
|
+
end
|
195
217
|
|
196
|
-
|
218
|
+
# For each element yielded by the response body, yield the element in chunked
|
219
|
+
# encoding.
|
220
|
+
def each(&block)
|
221
|
+
term = TERM
|
222
|
+
@body.each do |chunk|
|
223
|
+
size = chunk.bytesize
|
224
|
+
next if size == 0
|
225
|
+
|
226
|
+
yield [size.to_s(16), term, chunk.b, term].join
|
227
|
+
end
|
228
|
+
yield TAIL
|
229
|
+
yield term
|
230
|
+
end
|
231
|
+
|
232
|
+
# Close the response body if the response body supports it.
|
233
|
+
def close
|
234
|
+
@body.close if @body.respond_to?(:close)
|
235
|
+
end
|
236
|
+
end
|
197
237
|
|
238
|
+
private
|
198
239
|
# Set proper cache control and transfer encoding when streaming
|
199
|
-
def _process_options(options)
|
240
|
+
def _process_options(options)
|
200
241
|
super
|
201
242
|
if options[:stream]
|
202
|
-
if
|
243
|
+
if request.version == "HTTP/1.0"
|
203
244
|
options.delete(:stream)
|
204
245
|
else
|
205
246
|
headers["Cache-Control"] ||= "no-cache"
|
@@ -209,10 +250,10 @@ module ActionController #:nodoc:
|
|
209
250
|
end
|
210
251
|
end
|
211
252
|
|
212
|
-
# Call render_body if we are streaming instead of usual
|
213
|
-
def _render_template(options)
|
253
|
+
# Call render_body if we are streaming instead of usual `render`.
|
254
|
+
def _render_template(options)
|
214
255
|
if options.delete(:stream)
|
215
|
-
|
256
|
+
Body.new view_renderer.render_body(view_context, options)
|
216
257
|
else
|
217
258
|
super
|
218
259
|
end
|