actionpack 6.1.7 → 7.0.4.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.

Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +269 -406
  3. data/MIT-LICENSE +1 -0
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +13 -26
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +21 -7
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +4 -3
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +3 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +6 -6
  18. data/lib/action_controller/base.rb +5 -4
  19. data/lib/action_controller/form_builder.rb +2 -2
  20. data/lib/action_controller/log_subscriber.rb +4 -3
  21. data/lib/action_controller/metal/conditional_get.rb +39 -2
  22. data/lib/action_controller/metal/content_security_policy.rb +36 -2
  23. data/lib/action_controller/metal/cookies.rb +1 -1
  24. data/lib/action_controller/metal/data_streaming.rb +5 -13
  25. data/lib/action_controller/metal/exceptions.rb +19 -30
  26. data/lib/action_controller/metal/flash.rb +6 -2
  27. data/lib/action_controller/metal/helpers.rb +2 -2
  28. data/lib/action_controller/metal/http_authentication.rb +66 -39
  29. data/lib/action_controller/metal/instrumentation.rb +57 -52
  30. data/lib/action_controller/metal/live.rb +43 -2
  31. data/lib/action_controller/metal/mime_responds.rb +3 -3
  32. data/lib/action_controller/metal/params_wrapper.rb +20 -11
  33. data/lib/action_controller/metal/permissions_policy.rb +19 -28
  34. data/lib/action_controller/metal/redirecting.rb +93 -18
  35. data/lib/action_controller/metal/renderers.rb +10 -11
  36. data/lib/action_controller/metal/rendering.rb +8 -8
  37. data/lib/action_controller/metal/request_forgery_protection.rb +78 -29
  38. data/lib/action_controller/metal/rescue.rb +1 -1
  39. data/lib/action_controller/metal/streaming.rb +6 -8
  40. data/lib/action_controller/metal/strong_parameters.rb +100 -54
  41. data/lib/action_controller/metal/testing.rb +9 -2
  42. data/lib/action_controller/metal/url_for.rb +3 -3
  43. data/lib/action_controller/metal.rb +10 -13
  44. data/lib/action_controller/railtie.rb +49 -6
  45. data/lib/action_controller/renderer.rb +1 -1
  46. data/lib/action_controller/test_case.rb +28 -7
  47. data/lib/action_controller.rb +2 -5
  48. data/lib/action_dispatch/http/cache.rb +14 -7
  49. data/lib/action_dispatch/http/content_security_policy.rb +108 -35
  50. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  51. data/lib/action_dispatch/http/mime_negotiation.rb +15 -5
  52. data/lib/action_dispatch/http/mime_type.rb +9 -11
  53. data/lib/action_dispatch/http/parameters.rb +5 -5
  54. data/lib/action_dispatch/http/permissions_policy.rb +17 -1
  55. data/lib/action_dispatch/http/request.rb +12 -21
  56. data/lib/action_dispatch/http/response.rb +3 -16
  57. data/lib/action_dispatch/http/url.rb +11 -19
  58. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  59. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  60. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  61. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  62. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  63. data/lib/action_dispatch/journey/route.rb +6 -13
  64. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  65. data/lib/action_dispatch/journey/router.rb +1 -1
  66. data/lib/action_dispatch/journey/routes.rb +3 -3
  67. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  68. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  69. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  70. data/lib/action_dispatch/middleware/cookies.rb +42 -27
  71. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  72. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  73. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  74. data/lib/action_dispatch/middleware/executor.rb +3 -0
  75. data/lib/action_dispatch/middleware/flash.rb +17 -18
  76. data/lib/action_dispatch/middleware/host_authorization.rb +1 -12
  77. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  78. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  79. data/lib/action_dispatch/middleware/server_timing.rb +76 -0
  80. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  81. data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
  82. data/lib/action_dispatch/middleware/show_exceptions.rb +7 -9
  83. data/lib/action_dispatch/middleware/stack.rb +27 -9
  84. data/lib/action_dispatch/middleware/static.rb +2 -6
  85. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  86. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  87. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  88. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +3 -2
  89. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -0
  90. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  91. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  92. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  93. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  94. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  95. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  96. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  97. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  98. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  99. data/lib/action_dispatch/railtie.rb +8 -2
  100. data/lib/action_dispatch/request/session.rb +43 -13
  101. data/lib/action_dispatch/routing/inspector.rb +1 -1
  102. data/lib/action_dispatch/routing/mapper.rb +59 -83
  103. data/lib/action_dispatch/routing/redirection.rb +5 -2
  104. data/lib/action_dispatch/routing/route_set.rb +17 -7
  105. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  106. data/lib/action_dispatch/routing/url_for.rb +4 -5
  107. data/lib/action_dispatch/routing.rb +5 -6
  108. data/lib/action_dispatch/system_test_case.rb +5 -5
  109. data/lib/action_dispatch/system_testing/browser.rb +2 -12
  110. data/lib/action_dispatch/system_testing/driver.rb +35 -11
  111. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +11 -7
  112. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
  113. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  114. data/lib/action_dispatch/testing/assertions.rb +2 -5
  115. data/lib/action_dispatch/testing/integration.rb +6 -8
  116. data/lib/action_dispatch/testing/test_process.rb +3 -29
  117. data/lib/action_dispatch/testing/test_response.rb +20 -2
  118. data/lib/action_dispatch.rb +1 -0
  119. data/lib/action_pack/gem_version.rb +5 -5
  120. data/lib/action_pack/version.rb +1 -1
  121. metadata +16 -15
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/utils"
4
- require "active_support/core_ext/uri"
5
4
 
6
5
  module ActionDispatch
7
6
  # This middleware serves static files from disk, if available.
@@ -137,11 +136,8 @@ module ActionDispatch
137
136
  end
138
137
 
139
138
  def file_readable?(path)
140
- file_stat = File.stat(File.join(@root, path.b))
141
- rescue SystemCallError
142
- false
143
- else
144
- file_stat.file? && file_stat.readable?
139
+ file_path = File.join(@root, path.b)
140
+ File.file?(file_path) && File.readable?(file_path)
145
141
  end
146
142
 
147
143
  def compressible?(content_type)
@@ -11,7 +11,7 @@
11
11
  <b>Did you mean?</b>
12
12
  <ul>
13
13
  <% corrections.each do |correction| %>
14
- <li style="list-style-type: none"><%= h correction %></li>
14
+ <li class="correction"><%= h correction %></li>
15
15
  <% end %>
16
16
  </ul>
17
17
  <% end %>
@@ -1,24 +1,17 @@
1
- <% unless @exception.blamed_files.blank? %>
2
- <% if (hide = @exception.blamed_files.length > 8) %>
3
- <a href="#" onclick="return toggleTrace()">Toggle blamed files</a>
4
- <% end %>
5
- <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
6
- <% end %>
7
-
8
- <h2 style="margin-top: 30px">Request</h2>
1
+ <h2 class="request-heading">Request</h2>
9
2
  <% if params_valid? %>
10
3
  <p><b>Parameters</b>:</p> <pre><%= debug_params(@request.filtered_parameters) %></pre>
11
4
  <% end %>
12
5
 
13
6
  <div class="details">
14
7
  <div class="summary"><a href="#" onclick="return toggleSessionDump()">Toggle session dump</a></div>
15
- <div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
8
+ <div id="session_dump" class="hidden"><pre><%= debug_hash @request.session %></pre></div>
16
9
  </div>
17
10
 
18
11
  <div class="details">
19
12
  <div class="summary"><a href="#" onclick="return toggleEnvDump()">Toggle env dump</a></div>
20
- <div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
13
+ <div id="env_dump" class="hidden"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
21
14
  </div>
22
15
 
23
- <h2 style="margin-top: 30px">Response</h2>
16
+ <h2 class="response-heading">Response</h2>
24
17
  <p><b>Headers</b>:</p> <pre><%= debug_headers(defined?(@response) ? @response.headers : {}) %></pre>
@@ -14,7 +14,7 @@
14
14
 
15
15
  <% traces.each do |name, trace| %>
16
16
  <div id="<%= "#{name.gsub(/\s/, '-')}-#{error_index}" %>" style="display: <%= (name == trace_to_show) ? 'block' : 'none' %>;">
17
- <code style="font-size: 11px;">
17
+ <code class="traces">
18
18
  <% trace.each do |frame| %>
19
19
  <a class="trace-frames trace-frames-<%= error_index %>" data-exception-object-id="<%= frame[:exception_object_id] %>" data-frame-id="<%= frame[:id] %>" href="#">
20
20
  <%= frame[:trace] %>
@@ -25,7 +25,7 @@
25
25
  </div>
26
26
  <% end %>
27
27
 
28
- <script type="text/javascript">
28
+ <script>
29
29
  (function() {
30
30
  var traceFrames = document.getElementsByClassName('trace-frames-<%= error_index %>');
31
31
  var selectedFrame, currentSource = document.getElementById('frame-source-<%= error_index %>-0');
@@ -1,7 +1,8 @@
1
1
  <header>
2
2
  <h1>Blocked host: <%= @host %></h1>
3
3
  </header>
4
- <div id="container">
4
+ <main role="main" id="container">
5
5
  <h2>To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:</h2>
6
6
  <pre>config.hosts &lt;&lt; "<%= @host %>"</pre>
7
- </div>
7
+ <p>For more details view: <a href="https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization">the Host Authorization guide</a></p>
8
+ </main>
@@ -3,3 +3,5 @@ Blocked host: <%= @host %>
3
3
  To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
4
4
 
5
5
  config.hosts << "<%= @host %>"
6
+
7
+ For more details on host authorization view: https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization
@@ -7,7 +7,7 @@
7
7
  </h1>
8
8
  </header>
9
9
 
10
- <div id="container">
10
+ <main role="main" id="container">
11
11
  <%= render "rescues/message_and_suggestions", exception: @exception %>
12
12
  <%= render "rescues/actions", exception: @exception, request: @request %>
13
13
 
@@ -20,16 +20,16 @@
20
20
 
21
21
  <% @exception_wrapper.wrapped_causes.each.with_index(1) do |wrapper, index| %>
22
22
  <div class="details">
23
- <a class="summary" href="#" style="color: #F0F0F0; text-decoration: none; background: #C52F24; border-bottom: none;" onclick="return toggle(<%= wrapper.exception.object_id %>)">
23
+ <a class="summary" href="#" onclick="return toggle(<%= wrapper.exception.object_id %>)">
24
24
  <%= wrapper.exception.class.name %>: <%= h wrapper.exception.message %>
25
25
  </a>
26
26
  </div>
27
27
 
28
- <div id="<%= wrapper.exception.object_id %>" style="display: none;">
28
+ <div id="<%= wrapper.exception.object_id %>" class="hidden">
29
29
  <%= render "rescues/source", source_extracts: wrapper.source_extracts, show_source_idx: wrapper.source_to_show_id, error_index: index %>
30
30
  <%= render "rescues/trace", traces: wrapper.traces, trace_to_show: wrapper.trace_to_show, error_index: index %>
31
31
  </div>
32
32
  <% end %>
33
33
 
34
34
  <%= render template: "rescues/_request_and_response" %>
35
- </div>
35
+ </main>
@@ -1,4 +1,4 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>
3
3
  <%= @exception.class.to_s %>
4
4
  <% if @request.parameters['controller'] %>
@@ -7,7 +7,7 @@
7
7
  </h1>
8
8
  </header>
9
9
 
10
- <div id="container">
10
+ <main role="main" id="container">
11
11
  <h2>
12
12
  <%= h @exception.message %>
13
13
  <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
@@ -21,4 +21,4 @@
21
21
  <%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
22
22
  <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
23
23
  <%= render template: "rescues/_request_and_response" %>
24
- </div>
24
+ </main>
@@ -49,11 +49,19 @@
49
49
  line-height: 25px;
50
50
  }
51
51
 
52
+ code.traces {
53
+ font-size: 11px;
54
+ }
55
+
56
+ .response-heading, .request-heading {
57
+ margin-top: 30px;
58
+ }
59
+
52
60
  .exception-message {
53
61
  padding: 8px 0;
54
62
  }
55
63
 
56
- .exception-message .message{
64
+ .exception-message .message {
57
65
  margin-bottom: 8px;
58
66
  line-height: 25px;
59
67
  font-size: 1.5em;
@@ -75,6 +83,13 @@
75
83
  display: block;
76
84
  }
77
85
 
86
+ a.summary {
87
+ color: #F0F0F0;
88
+ text-decoration: none;
89
+ background: #C52F24;
90
+ border-bottom: none;
91
+ }
92
+
78
93
  .details pre {
79
94
  margin: 5px;
80
95
  border: none;
@@ -114,7 +129,7 @@
114
129
 
115
130
  .source .data .line_numbers {
116
131
  background-color: #ECECEC;
117
- color: #AAA;
132
+ color: #555;
118
133
  padding: 1em .5em;
119
134
  border-right: 1px solid #DDD;
120
135
  text-align: right;
@@ -143,6 +158,10 @@
143
158
  display: none;
144
159
  }
145
160
 
161
+ .correction {
162
+ list-style-type: none;
163
+ }
164
+
146
165
  input[type="submit"] {
147
166
  color: white;
148
167
  background-color: #C00;
@@ -153,6 +172,7 @@
153
172
  font-weight: bold;
154
173
  margin: 0;
155
174
  padding: 10px 18px;
175
+ cursor: pointer;
156
176
  -webkit-appearance: none;
157
177
  }
158
178
  input[type="submit"]:focus,
@@ -164,15 +184,14 @@
164
184
  transform: translateY(1px)
165
185
  }
166
186
 
167
-
168
187
  a { color: #980905; }
169
188
  a:visited { color: #666; }
170
189
  a.trace-frames {
171
190
  color: #666;
172
191
  overflow-wrap: break-word;
173
192
  }
174
- a:hover { color: #C00; }
175
- a.trace-frames.selected { color: #C00 }
193
+ a:hover, a.trace-frames.selected { color: #C00; }
194
+ a.summary:hover { color: #FFF; }
176
195
 
177
196
  @media (prefers-color-scheme: dark) {
178
197
  body {
@@ -180,11 +199,7 @@
180
199
  color: #ECECEC;
181
200
  }
182
201
 
183
- .details {
184
- border-color: #666;
185
- }
186
-
187
- .summary {
202
+ .details, .summary {
188
203
  border-color: #666;
189
204
  }
190
205
 
@@ -219,8 +234,7 @@
219
234
 
220
235
  a { color: #C00; }
221
236
  a.trace-frames { color: #999; }
222
- a:hover { color: #E9382B; }
223
- a.trace-frames.selected { color: #E9382B; }
237
+ a:hover, a.trace-frames.selected { color: #E9382B; }
224
238
  }
225
239
 
226
240
  <%= yield :style %>
@@ -228,8 +242,7 @@
228
242
 
229
243
  <script>
230
244
  var toggle = function(id) {
231
- var s = document.getElementById(id).style;
232
- s.display = s.display == 'none' ? 'block' : 'none';
245
+ document.getElementById(id).classList.toggle('hidden');
233
246
  return false;
234
247
  }
235
248
  var show = function(id) {
@@ -238,9 +251,6 @@
238
251
  var hide = function(id) {
239
252
  document.getElementById(id).style.display = 'none';
240
253
  }
241
- var toggleTrace = function() {
242
- return toggle('blame_trace');
243
- }
244
254
  var toggleSessionDump = function() {
245
255
  return toggle('session_dump');
246
256
  }
@@ -251,7 +261,7 @@
251
261
  </head>
252
262
  <body>
253
263
 
254
- <%= yield %>
264
+ <%= yield %>
255
265
 
256
266
  </body>
257
267
  </html>
@@ -1,8 +1,8 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>No template for interactive request</h1>
3
3
  </header>
4
4
 
5
- <div id="container">
5
+ <main id="container">
6
6
  <h2><%= h @exception.message %></h2>
7
7
 
8
8
  <p class="summary">
@@ -16,4 +16,4 @@
16
16
  since we expect an HTML template
17
17
  to be rendered for such requests. If that's the case, carry on.
18
18
  </p>
19
- </div>
19
+ </main>
@@ -1,11 +1,11 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>Template is missing</h1>
3
3
  </header>
4
4
 
5
- <div id="container">
5
+ <main role="main" id="container">
6
6
  <h2><%= h @exception.message %></h2>
7
7
 
8
8
  <%= render "rescues/source", source_extracts: @source_extracts, show_source_idx: @show_source_idx %>
9
9
  <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
10
10
  <%= render template: "rescues/_request_and_response" %>
11
- </div>
11
+ </main>
@@ -1,7 +1,7 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>Routing Error</h1>
3
3
  </header>
4
- <div id="container">
4
+ <main role="main" id="container">
5
5
  <h2><%= h @exception.message %></h2>
6
6
  <% unless @exception.failures.empty? %>
7
7
  <p>
@@ -29,4 +29,4 @@
29
29
  <% end %>
30
30
 
31
31
  <%= render template: "rescues/_request_and_response" %>
32
- </div>
32
+ </main>
@@ -1,11 +1,11 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>
3
3
  <%= @exception.cause.class.to_s %> in
4
4
  <%= @request.parameters["controller"].camelize if @request.parameters["controller"] %>#<%= @request.parameters["action"] %>
5
5
  </h1>
6
6
  </header>
7
7
 
8
- <div id="container">
8
+ <main role="main" id="container">
9
9
  <p>
10
10
  Showing <i><%= @exception.file_name %></i> where line <b>#<%= @exception.line_number %></b> raised:
11
11
  </p>
@@ -17,4 +17,4 @@
17
17
 
18
18
  <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
19
19
  <%= render template: "rescues/_request_and_response" %>
20
- </div>
20
+ </main>
@@ -1,6 +1,6 @@
1
- <header>
1
+ <header role="banner">
2
2
  <h1>Unknown action</h1>
3
3
  </header>
4
- <div id="container">
4
+ <main role="main" id="container">
5
5
  <%= render "rescues/message_and_suggestions", exception: @exception %>
6
- </div>
6
+ </main>
@@ -51,22 +51,13 @@
51
51
  }
52
52
 
53
53
  @media (prefers-color-scheme: dark) {
54
- body {
55
- background-color: #222;
56
- color: #ECECEC;
57
- }
58
-
59
54
  #route_table tbody tr:nth-child(odd) {
60
- background: #333;
61
- }
62
-
63
- #route_table tbody tr:nth-child(even) {
64
- background: #444;
55
+ background: #282828;
65
56
  }
66
57
 
67
- #route_table tbody.exact_matches,
68
- #route_table tbody.fuzzy_matches {
69
- color: #333;
58
+ #route_table tbody.exact_matches tr,
59
+ #route_table tbody.fuzzy_matches tr {
60
+ background: DarkSlateGrey;
70
61
  }
71
62
  }
72
63
  <% end %>
@@ -104,7 +95,7 @@
104
95
  </tbody>
105
96
  </table>
106
97
 
107
- <script type='text/javascript'>
98
+ <script>
108
99
  // support forEach iterator on NodeList
109
100
  NodeList.prototype.forEach = Array.prototype.forEach;
110
101
 
@@ -24,6 +24,8 @@ module ActionDispatch
24
24
  config.action_dispatch.use_cookies_with_metadata = false
25
25
  config.action_dispatch.perform_deep_munge = true
26
26
  config.action_dispatch.request_id_header = "X-Request-Id"
27
+ config.action_dispatch.return_only_request_media_type_on_content_type = true
28
+ config.action_dispatch.log_rescued_responses = true
27
29
 
28
30
  config.action_dispatch.default_headers = {
29
31
  "X-Frame-Options" => "SAMEORIGIN",
@@ -41,8 +43,12 @@ module ActionDispatch
41
43
  initializer "action_dispatch.configure" do |app|
42
44
  ActionDispatch::Http::URL.secure_protocol = app.config.force_ssl
43
45
  ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
44
- ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
45
- ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
46
+
47
+ ActiveSupport.on_load(:action_dispatch_request) do
48
+ self.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
49
+ self.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_request_media_type_on_content_type
50
+ ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
51
+ end
46
52
 
47
53
  ActiveSupport.on_load(:action_dispatch_response) do
48
54
  self.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
@@ -6,6 +6,7 @@ module ActionDispatch
6
6
  class Request
7
7
  # Session is responsible for lazily loading the session from store.
8
8
  class Session # :nodoc:
9
+ DisabledSessionError = Class.new(StandardError)
9
10
  ENV_SESSION_KEY = Rack::RACK_SESSION # :nodoc:
10
11
  ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS # :nodoc:
11
12
 
@@ -23,6 +24,12 @@ module ActionDispatch
23
24
  session
24
25
  end
25
26
 
27
+ def self.disabled(req)
28
+ new(nil, req, enabled: false).tap do
29
+ Session::Options.set(req, Session::Options.new(nil, { id: nil }))
30
+ end
31
+ end
32
+
26
33
  def self.find(req)
27
34
  req.get_header ENV_SESSION_KEY
28
35
  end
@@ -31,7 +38,11 @@ module ActionDispatch
31
38
  req.set_header ENV_SESSION_KEY, session
32
39
  end
33
40
 
34
- class Options #:nodoc:
41
+ def self.delete(req)
42
+ req.delete_header ENV_SESSION_KEY
43
+ end
44
+
45
+ class Options # :nodoc:
35
46
  def self.set(req, options)
36
47
  req.set_header ENV_SESSION_OPTIONS_KEY, options
37
48
  end
@@ -60,30 +71,38 @@ module ActionDispatch
60
71
  def values_at(*args); @delegate.values_at(*args); end
61
72
  end
62
73
 
63
- def initialize(by, req)
74
+ def initialize(by, req, enabled: true)
64
75
  @by = by
65
76
  @req = req
66
77
  @delegate = {}
67
78
  @loaded = false
68
79
  @exists = nil # We haven't checked yet.
80
+ @enabled = enabled
69
81
  end
70
82
 
71
83
  def id
72
84
  options.id(@req)
73
85
  end
74
86
 
87
+ def enabled?
88
+ @enabled
89
+ end
90
+
75
91
  def options
76
92
  Options.find @req
77
93
  end
78
94
 
79
95
  def destroy
80
96
  clear
81
- options = self.options || {}
82
- @by.send(:delete_session, @req, options.id(@req), options)
83
97
 
84
- # Load the new sid to be written with the response.
85
- @loaded = false
86
- load_for_write!
98
+ if enabled?
99
+ options = self.options || {}
100
+ @by.send(:delete_session, @req, options.id(@req), options)
101
+
102
+ # Load the new sid to be written with the response.
103
+ @loaded = false
104
+ load_for_write!
105
+ end
87
106
  end
88
107
 
89
108
  # Returns value of the key stored in the session or
@@ -135,7 +154,7 @@ module ActionDispatch
135
154
 
136
155
  # Clears the session.
137
156
  def clear
138
- load_for_write!
157
+ load_for_delete!
139
158
  @delegate.clear
140
159
  end
141
160
 
@@ -163,7 +182,7 @@ module ActionDispatch
163
182
 
164
183
  # Deletes given key from the session.
165
184
  def delete(key)
166
- load_for_write!
185
+ load_for_delete!
167
186
  @delegate.delete key.to_s
168
187
  end
169
188
 
@@ -199,6 +218,7 @@ module ActionDispatch
199
218
  end
200
219
 
201
220
  def exists?
221
+ return false unless enabled?
202
222
  return @exists unless @exists.nil?
203
223
  @exists = @by.send(:session_exists?, @req)
204
224
  end
@@ -227,13 +247,23 @@ module ActionDispatch
227
247
  end
228
248
 
229
249
  def load_for_write!
230
- load! unless loaded?
250
+ if enabled?
251
+ load! unless loaded?
252
+ else
253
+ raise DisabledSessionError, "Your application has sessions disabled. To write to the session you must first configure a session store"
254
+ end
255
+ end
256
+
257
+ def load_for_delete!
258
+ load! if enabled? && !loaded?
231
259
  end
232
260
 
233
261
  def load!
234
- id, session = @by.load_session @req
235
- options[:id] = id
236
- @delegate.replace(session.stringify_keys)
262
+ if enabled?
263
+ id, session = @by.load_session @req
264
+ options[:id] = id
265
+ @delegate.replace(session.stringify_keys)
266
+ end
237
267
  @loaded = true
238
268
  end
239
269
  end
@@ -5,7 +5,7 @@ require "io/console/size"
5
5
 
6
6
  module ActionDispatch
7
7
  module Routing
8
- class RouteWrapper < SimpleDelegator
8
+ class RouteWrapper < SimpleDelegator # :nodoc:
9
9
  def endpoint
10
10
  app.dispatcher? ? "#{controller}##{action}" : rack_app.inspect
11
11
  end