actionpack 4.2.11.1 → 6.1.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +291 -489
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -9
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +81 -51
  7. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +64 -17
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +61 -33
  10. data/lib/abstract_controller/collector.rb +9 -13
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +115 -99
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +21 -3
  15. data/lib/abstract_controller/rendering.rb +48 -47
  16. data/lib/abstract_controller/translation.rb +17 -8
  17. data/lib/abstract_controller/url_for.rb +2 -0
  18. data/lib/abstract_controller.rb +13 -5
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +150 -0
  21. data/lib/action_controller/base.rb +29 -24
  22. data/lib/action_controller/caching.rb +12 -57
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +17 -19
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +134 -46
  27. data/lib/action_controller/metal/content_security_policy.rb +51 -0
  28. data/lib/action_controller/metal/cookies.rb +6 -4
  29. data/lib/action_controller/metal/data_streaming.rb +30 -50
  30. data/lib/action_controller/metal/default_headers.rb +17 -0
  31. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  32. data/lib/action_controller/metal/etag_with_template_digest.rb +21 -16
  33. data/lib/action_controller/metal/exceptions.rb +63 -15
  34. data/lib/action_controller/metal/flash.rb +9 -8
  35. data/lib/action_controller/metal/head.rb +26 -21
  36. data/lib/action_controller/metal/helpers.rb +37 -18
  37. data/lib/action_controller/metal/http_authentication.rb +81 -73
  38. data/lib/action_controller/metal/implicit_render.rb +53 -9
  39. data/lib/action_controller/metal/instrumentation.rb +32 -35
  40. data/lib/action_controller/metal/live.rb +102 -120
  41. data/lib/action_controller/metal/logging.rb +20 -0
  42. data/lib/action_controller/metal/mime_responds.rb +49 -47
  43. data/lib/action_controller/metal/parameter_encoding.rb +82 -0
  44. data/lib/action_controller/metal/params_wrapper.rb +83 -66
  45. data/lib/action_controller/metal/permissions_policy.rb +46 -0
  46. data/lib/action_controller/metal/redirecting.rb +53 -32
  47. data/lib/action_controller/metal/renderers.rb +87 -44
  48. data/lib/action_controller/metal/rendering.rb +77 -50
  49. data/lib/action_controller/metal/request_forgery_protection.rb +267 -103
  50. data/lib/action_controller/metal/rescue.rb +10 -17
  51. data/lib/action_controller/metal/streaming.rb +12 -11
  52. data/lib/action_controller/metal/strong_parameters.rb +714 -186
  53. data/lib/action_controller/metal/testing.rb +2 -17
  54. data/lib/action_controller/metal/url_for.rb +19 -10
  55. data/lib/action_controller/metal.rb +104 -87
  56. data/lib/action_controller/railtie.rb +28 -10
  57. data/lib/action_controller/railties/helpers.rb +3 -1
  58. data/lib/action_controller/renderer.rb +141 -0
  59. data/lib/action_controller/template_assertions.rb +11 -0
  60. data/lib/action_controller/test_case.rb +296 -422
  61. data/lib/action_controller.rb +34 -23
  62. data/lib/action_dispatch/http/cache.rb +107 -56
  63. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  64. data/lib/action_dispatch/http/content_security_policy.rb +286 -0
  65. data/lib/action_dispatch/http/filter_parameters.rb +32 -25
  66. data/lib/action_dispatch/http/filter_redirect.rb +10 -12
  67. data/lib/action_dispatch/http/headers.rb +55 -22
  68. data/lib/action_dispatch/http/mime_negotiation.rb +79 -51
  69. data/lib/action_dispatch/http/mime_type.rb +153 -121
  70. data/lib/action_dispatch/http/mime_types.rb +20 -6
  71. data/lib/action_dispatch/http/parameters.rb +90 -40
  72. data/lib/action_dispatch/http/permissions_policy.rb +173 -0
  73. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  74. data/lib/action_dispatch/http/request.rb +226 -121
  75. data/lib/action_dispatch/http/response.rb +248 -113
  76. data/lib/action_dispatch/http/upload.rb +21 -7
  77. data/lib/action_dispatch/http/url.rb +182 -100
  78. data/lib/action_dispatch/journey/formatter.rb +90 -43
  79. data/lib/action_dispatch/journey/gtg/builder.rb +28 -41
  80. data/lib/action_dispatch/journey/gtg/simulator.rb +11 -16
  81. data/lib/action_dispatch/journey/gtg/transition_table.rb +23 -21
  82. data/lib/action_dispatch/journey/nfa/dot.rb +3 -14
  83. data/lib/action_dispatch/journey/nodes/node.rb +29 -15
  84. data/lib/action_dispatch/journey/parser.rb +17 -16
  85. data/lib/action_dispatch/journey/parser.y +4 -3
  86. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  87. data/lib/action_dispatch/journey/path/pattern.rb +58 -54
  88. data/lib/action_dispatch/journey/route.rb +100 -32
  89. data/lib/action_dispatch/journey/router/utils.rb +29 -18
  90. data/lib/action_dispatch/journey/router.rb +55 -51
  91. data/lib/action_dispatch/journey/routes.rb +17 -17
  92. data/lib/action_dispatch/journey/scanner.rb +26 -17
  93. data/lib/action_dispatch/journey/visitors.rb +98 -54
  94. data/lib/action_dispatch/journey.rb +5 -5
  95. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  96. data/lib/action_dispatch/middleware/callbacks.rb +3 -6
  97. data/lib/action_dispatch/middleware/cookies.rb +347 -217
  98. data/lib/action_dispatch/middleware/debug_exceptions.rb +135 -63
  99. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  100. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  101. data/lib/action_dispatch/middleware/exception_wrapper.rb +115 -71
  102. data/lib/action_dispatch/middleware/executor.rb +21 -0
  103. data/lib/action_dispatch/middleware/flash.rb +78 -54
  104. data/lib/action_dispatch/middleware/host_authorization.rb +130 -0
  105. data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
  106. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  107. data/lib/action_dispatch/middleware/remote_ip.rb +53 -45
  108. data/lib/action_dispatch/middleware/request_id.rb +17 -10
  109. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
  110. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  111. data/lib/action_dispatch/middleware/session/cookie_store.rb +74 -75
  112. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  113. data/lib/action_dispatch/middleware/show_exceptions.rb +28 -23
  114. data/lib/action_dispatch/middleware/ssl.rb +118 -35
  115. data/lib/action_dispatch/middleware/stack.rb +82 -41
  116. data/lib/action_dispatch/middleware/static.rb +156 -89
  117. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -14
  121. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
  123. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  124. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  125. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  126. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  129. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +105 -8
  132. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  135. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  136. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  137. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  138. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  139. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  140. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +87 -64
  141. data/lib/action_dispatch/railtie.rb +27 -13
  142. data/lib/action_dispatch/request/session.rb +109 -61
  143. data/lib/action_dispatch/request/utils.rb +90 -23
  144. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  145. data/lib/action_dispatch/routing/inspector.rb +141 -102
  146. data/lib/action_dispatch/routing/mapper.rb +811 -473
  147. data/lib/action_dispatch/routing/polymorphic_routes.rb +167 -143
  148. data/lib/action_dispatch/routing/redirection.rb +37 -27
  149. data/lib/action_dispatch/routing/route_set.rb +363 -331
  150. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  151. data/lib/action_dispatch/routing/url_for.rb +66 -26
  152. data/lib/action_dispatch/routing.rb +36 -36
  153. data/lib/action_dispatch/system_test_case.rb +190 -0
  154. data/lib/action_dispatch/system_testing/browser.rb +86 -0
  155. data/lib/action_dispatch/system_testing/driver.rb +67 -0
  156. data/lib/action_dispatch/system_testing/server.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +138 -0
  158. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +29 -0
  159. data/lib/action_dispatch/testing/assertion_response.rb +46 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +44 -22
  161. data/lib/action_dispatch/testing/assertions/routing.rb +47 -31
  162. data/lib/action_dispatch/testing/assertions.rb +6 -4
  163. data/lib/action_dispatch/testing/integration.rb +391 -220
  164. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  165. data/lib/action_dispatch/testing/test_process.rb +53 -22
  166. data/lib/action_dispatch/testing/test_request.rb +27 -34
  167. data/lib/action_dispatch/testing/test_response.rb +11 -11
  168. data/lib/action_dispatch.rb +35 -21
  169. data/lib/action_pack/gem_version.rb +6 -4
  170. data/lib/action_pack/version.rb +3 -1
  171. data/lib/action_pack.rb +4 -2
  172. metadata +78 -48
  173. data/lib/action_controller/metal/force_ssl.rb +0 -97
  174. data/lib/action_controller/metal/hide_actions.rb +0 -40
  175. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  176. data/lib/action_controller/middleware.rb +0 -39
  177. data/lib/action_controller/model_naming.rb +0 -12
  178. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  179. data/lib/action_dispatch/journey/backwards.rb +0 -5
  180. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  181. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  182. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  183. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  184. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  185. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  186. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  187. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -17,6 +17,10 @@
17
17
  line-height: 15px;
18
18
  }
19
19
 
20
+ #route_table thead tr.bottom th input#search {
21
+ -webkit-appearance: textfield;
22
+ }
23
+
20
24
  #route_table tbody tr {
21
25
  border-bottom: 1px solid #ddd;
22
26
  }
@@ -45,6 +49,26 @@
45
49
  width: 80%;
46
50
  font-size: inherit;
47
51
  }
52
+
53
+ @media (prefers-color-scheme: dark) {
54
+ body {
55
+ background-color: #222;
56
+ color: #ECECEC;
57
+ }
58
+
59
+ #route_table tbody tr:nth-child(odd) {
60
+ background: #333;
61
+ }
62
+
63
+ #route_table tbody tr:nth-child(even) {
64
+ background: #444;
65
+ }
66
+
67
+ #route_table tbody.exact_matches,
68
+ #route_table tbody.fuzzy_matches {
69
+ color: #333;
70
+ }
71
+ }
48
72
  <% end %>
49
73
 
50
74
  <table id='route_table' class='route_table'>
@@ -60,7 +84,7 @@
60
84
  <%= link_to "Path", "#", 'data-route-helper' => '_path',
61
85
  title: "Returns a relative path (without the http or domain)" %> /
62
86
  <%= link_to "Url", "#", 'data-route-helper' => '_url',
63
- title: "Returns an absolute url (with the http and domain)" %>
87
+ title: "Returns an absolute URL (with the http and domain)" %>
64
88
  </th>
65
89
  <th><%# HTTP Verb %>
66
90
  </th>
@@ -81,92 +105,87 @@
81
105
  </table>
82
106
 
83
107
  <script type='text/javascript'>
84
- // Iterates each element through a function
85
- function each(elems, func) {
86
- if (!elems instanceof Array) { elems = [elems]; }
87
- for (var i = 0, len = elems.length; i < len; i++) {
88
- func(elems[i]);
89
- }
90
- }
91
-
92
- // Sets innerHTML for an element
93
- function setContent(elem, text) {
94
- elem.innerHTML = text;
95
- }
108
+ // support forEach iterator on NodeList
109
+ NodeList.prototype.forEach = Array.prototype.forEach;
96
110
 
97
111
  // Enables path search functionality
98
112
  function setupMatchPaths() {
99
- // Check if the user input (sanitized as a path) matches the regexp data attribute
100
- function checkExactMatch(section, elem, value) {
101
- var string = sanitizePath(value),
102
- regexp = elem.getAttribute("data-regexp");
103
-
104
- showMatch(string, regexp, section, elem);
105
- }
106
-
107
- // Check if the route path data attribute contains the user input
108
- function checkFuzzyMatch(section, elem, value) {
109
- var string = elem.getAttribute("data-route-path"),
110
- regexp = value;
111
-
112
- showMatch(string, regexp, section, elem);
113
+ // Check if there are any matched results in a section
114
+ function checkNoMatch(section, noMatchText) {
115
+ if (section.children.length <= 1) {
116
+ section.innerHTML += noMatchText;
117
+ }
113
118
  }
114
119
 
115
- // Display the parent <tr> element in the appropriate section when there's a match
116
- function showMatch(string, regexp, section, elem) {
117
- if(string.match(RegExp(regexp))) {
118
- section.appendChild(elem.parentNode.cloneNode(true));
119
- }
120
+ // get JSON from URL and invoke callback with result
121
+ function getJSON(url, success) {
122
+ var xhr = new XMLHttpRequest();
123
+ xhr.open('GET', url);
124
+ xhr.onload = function() {
125
+ if (this.status == 200)
126
+ success(JSON.parse(this.response));
127
+ };
128
+ xhr.send();
120
129
  }
121
130
 
122
- // Check if there are any matched results in a section
123
- function checkNoMatch(section, defaultText, noMatchText) {
124
- if (section.innerHTML === defaultText) {
125
- setContent(section, defaultText + noMatchText);
131
+ function delayedKeyup(input, callback) {
132
+ var timeout;
133
+ input.onkeyup = function(){
134
+ if (timeout) clearTimeout(timeout);
135
+ timeout = setTimeout(callback, 300);
126
136
  }
127
137
  }
128
138
 
129
- // Ensure path always starts with a slash "/" and remove params or fragments
139
+ // remove params or fragments
130
140
  function sanitizePath(path) {
131
- var path = path.charAt(0) == '/' ? path : "/" + path;
132
- return path.replace(/\#.*|\?.*/, '');
141
+ return path.replace(/[#?].*/, '');
133
142
  }
134
143
 
135
- var regexpElems = document.querySelectorAll('#route_table [data-regexp]'),
136
- searchElem = document.querySelector('#search'),
137
- exactMatches = document.querySelector('#exact_matches'),
138
- fuzzyMatches = document.querySelector('#fuzzy_matches');
144
+ var pathElements = document.querySelectorAll('#route_table [data-route-path]'),
145
+ searchElem = document.querySelector('#search'),
146
+ exactSection = document.querySelector('#exact_matches'),
147
+ fuzzySection = document.querySelector('#fuzzy_matches');
139
148
 
140
149
  // Remove matches when no search value is present
141
150
  searchElem.onblur = function(e) {
142
151
  if (searchElem.value === "") {
143
- setContent(exactMatches, "");
144
- setContent(fuzzyMatches, "");
152
+ exactSection.innerHTML = "";
153
+ fuzzySection.innerHTML = "";
145
154
  }
146
155
  }
147
156
 
148
157
  // On key press perform a search for matching paths
149
- searchElem.onkeyup = function(e){
150
- var userInput = searchElem.value,
151
- defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + escape(sanitizePath(userInput)) +'):</th></tr>',
152
- defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + escape(userInput) +'):</th></tr>',
158
+ delayedKeyup(searchElem, function() {
159
+ var path = sanitizePath(searchElem.value),
160
+ defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + path +'):</th></tr>',
161
+ defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + path +'):</th></tr>',
153
162
  noExactMatch = '<tr><th colspan="4">No Exact Matches Found</th></tr>',
154
163
  noFuzzyMatch = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>';
155
164
 
156
- // Clear out results section
157
- setContent(exactMatches, defaultExactMatch);
158
- setContent(fuzzyMatches, defaultFuzzyMatch);
165
+ if (!path)
166
+ return searchElem.onblur();
159
167
 
160
- // Display exact matches and fuzzy matches
161
- each(regexpElems, function(elem) {
162
- checkExactMatch(exactMatches, elem, userInput);
163
- checkFuzzyMatch(fuzzyMatches, elem, userInput);
164
- })
168
+ getJSON('/rails/info/routes?path=' + path, function(matches){
169
+ // Clear out results section
170
+ exactSection.innerHTML = defaultExactMatch;
171
+ fuzzySection.innerHTML = defaultFuzzyMatch;
165
172
 
166
- // Display 'No Matches' message when no matches are found
167
- checkNoMatch(exactMatches, defaultExactMatch, noExactMatch);
168
- checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch);
169
- }
173
+ // Display exact matches and fuzzy matches
174
+ pathElements.forEach(function(elem) {
175
+ var elemPath = elem.getAttribute('data-route-path');
176
+
177
+ if (matches['exact'].indexOf(elemPath) != -1)
178
+ exactSection.appendChild(elem.parentNode.cloneNode(true));
179
+
180
+ if (matches['fuzzy'].indexOf(elemPath) != -1)
181
+ fuzzySection.appendChild(elem.parentNode.cloneNode(true));
182
+ })
183
+
184
+ // Display 'No Matches' message when no matches are found
185
+ checkNoMatch(exactSection, noExactMatch);
186
+ checkNoMatch(fuzzySection, noFuzzyMatch);
187
+ })
188
+ })
170
189
  }
171
190
 
172
191
  // Enables functionality to toggle between `_path` and `_url` helper suffixes
@@ -174,19 +193,20 @@
174
193
 
175
194
  // Sets content for each element
176
195
  function setValOn(elems, val) {
177
- each(elems, function(elem) {
178
- setContent(elem, val);
196
+ elems.forEach(function(elem) {
197
+ elem.innerHTML = val;
179
198
  });
180
199
  }
181
200
 
182
201
  // Sets onClick event for each element
183
202
  function onClick(elems, func) {
184
- each(elems, function(elem) {
203
+ elems.forEach(function(elem) {
185
204
  elem.onclick = func;
186
205
  });
187
206
  }
188
207
 
189
208
  var toggleLinks = document.querySelectorAll('#route_table [data-route-helper]');
209
+
190
210
  onClick(toggleLinks, function(){
191
211
  var helperTxt = this.getAttribute("data-route-helper"),
192
212
  helperElems = document.querySelectorAll('[data-route-name] span.helper');
@@ -197,4 +217,7 @@
197
217
 
198
218
  setupMatchPaths();
199
219
  setupRouteToggleHelperLinks();
220
+
221
+ // Focus the search input after page has loaded
222
+ document.getElementById('search').focus();
200
223
  </script>
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_dispatch"
4
+ require "active_support/messages/rotation_configuration"
2
5
 
3
6
  module ActionDispatch
4
7
  class Railtie < Rails::Railtie # :nodoc:
@@ -8,30 +11,43 @@ module ActionDispatch
8
11
  config.action_dispatch.show_exceptions = true
9
12
  config.action_dispatch.tld_length = 1
10
13
  config.action_dispatch.ignore_accept_header = false
11
- config.action_dispatch.rescue_templates = { }
12
- config.action_dispatch.rescue_responses = { }
14
+ config.action_dispatch.rescue_templates = {}
15
+ config.action_dispatch.rescue_responses = {}
13
16
  config.action_dispatch.default_charset = nil
14
17
  config.action_dispatch.rack_cache = false
15
- config.action_dispatch.http_auth_salt = 'http authentication'
16
- config.action_dispatch.signed_cookie_salt = 'signed cookie'
17
- config.action_dispatch.encrypted_cookie_salt = 'encrypted cookie'
18
- config.action_dispatch.encrypted_signed_cookie_salt = 'signed encrypted cookie'
18
+ config.action_dispatch.http_auth_salt = "http authentication"
19
+ config.action_dispatch.signed_cookie_salt = "signed cookie"
20
+ config.action_dispatch.encrypted_cookie_salt = "encrypted cookie"
21
+ config.action_dispatch.encrypted_signed_cookie_salt = "signed encrypted cookie"
22
+ config.action_dispatch.authenticated_encrypted_cookie_salt = "authenticated encrypted cookie"
23
+ config.action_dispatch.use_authenticated_cookie_encryption = false
24
+ config.action_dispatch.use_cookies_with_metadata = false
19
25
  config.action_dispatch.perform_deep_munge = true
26
+ config.action_dispatch.request_id_header = "X-Request-Id"
20
27
 
21
28
  config.action_dispatch.default_headers = {
22
- 'X-Frame-Options' => 'SAMEORIGIN',
23
- 'X-XSS-Protection' => '1; mode=block',
24
- 'X-Content-Type-Options' => 'nosniff'
29
+ "X-Frame-Options" => "SAMEORIGIN",
30
+ "X-XSS-Protection" => "1; mode=block",
31
+ "X-Content-Type-Options" => "nosniff",
32
+ "X-Download-Options" => "noopen",
33
+ "X-Permitted-Cross-Domain-Policies" => "none",
34
+ "Referrer-Policy" => "strict-origin-when-cross-origin"
25
35
  }
26
36
 
37
+ config.action_dispatch.cookies_rotations = ActiveSupport::Messages::RotationConfiguration.new
38
+
27
39
  config.eager_load_namespaces << ActionDispatch
28
40
 
29
41
  initializer "action_dispatch.configure" do |app|
42
+ ActionDispatch::Http::URL.secure_protocol = app.config.force_ssl
30
43
  ActionDispatch::Http::URL.tld_length = app.config.action_dispatch.tld_length
31
44
  ActionDispatch::Request.ignore_accept_header = app.config.action_dispatch.ignore_accept_header
32
45
  ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge
33
- ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
34
- ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers
46
+
47
+ ActiveSupport.on_load(:action_dispatch_response) do
48
+ self.default_charset = app.config.action_dispatch.default_charset || app.config.encoding
49
+ self.default_headers = app.config.action_dispatch.default_headers
50
+ end
35
51
 
36
52
  ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
37
53
  ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates)
@@ -40,8 +56,6 @@ module ActionDispatch
40
56
  ActionDispatch::Cookies::CookieJar.always_write_cookie = config.action_dispatch.always_write_cookie
41
57
 
42
58
  ActionDispatch.test_app = app
43
-
44
- ActionDispatch::Routing::RouteSet.relative_url_root = app.config.relative_url_root
45
59
  end
46
60
  end
47
61
  end
@@ -1,95 +1,113 @@
1
- require 'rack/session/abstract/id'
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/session/abstract/id"
2
4
 
3
5
  module ActionDispatch
4
- class Request < Rack::Request
6
+ class Request
5
7
  # Session is responsible for lazily loading the session from store.
6
8
  class Session # :nodoc:
7
- ENV_SESSION_KEY = Rack::Session::Abstract::ENV_SESSION_KEY # :nodoc:
8
- ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY # :nodoc:
9
+ ENV_SESSION_KEY = Rack::RACK_SESSION # :nodoc:
10
+ ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS # :nodoc:
9
11
 
10
- # Singleton object used to determine if an optional param wasn't specified
12
+ # Singleton object used to determine if an optional param wasn't specified.
11
13
  Unspecified = Object.new
12
14
 
13
- def self.create(store, env, default_options)
14
- session_was = find env
15
- session = Request::Session.new(store, env)
15
+ # Creates a session hash, merging the properties of the previous session if any.
16
+ def self.create(store, req, default_options)
17
+ session_was = find req
18
+ session = Request::Session.new(store, req)
16
19
  session.merge! session_was if session_was
17
20
 
18
- set(env, session)
19
- Options.set(env, Request::Session::Options.new(store, env, default_options))
21
+ set(req, session)
22
+ Options.set(req, Request::Session::Options.new(store, default_options))
20
23
  session
21
24
  end
22
25
 
23
- def self.find(env)
24
- env[ENV_SESSION_KEY]
26
+ def self.find(req)
27
+ req.get_header ENV_SESSION_KEY
25
28
  end
26
29
 
27
- def self.set(env, session)
28
- env[ENV_SESSION_KEY] = session
30
+ def self.set(req, session)
31
+ req.set_header ENV_SESSION_KEY, session
29
32
  end
30
33
 
31
34
  class Options #:nodoc:
32
- def self.set(env, options)
33
- env[ENV_SESSION_OPTIONS_KEY] = options
35
+ def self.set(req, options)
36
+ req.set_header ENV_SESSION_OPTIONS_KEY, options
34
37
  end
35
38
 
36
- def self.find(env)
37
- env[ENV_SESSION_OPTIONS_KEY]
39
+ def self.find(req)
40
+ req.get_header ENV_SESSION_OPTIONS_KEY
38
41
  end
39
42
 
40
- def initialize(by, env, default_options)
43
+ def initialize(by, default_options)
41
44
  @by = by
42
- @env = env
43
45
  @delegate = default_options.dup
44
46
  end
45
47
 
46
48
  def [](key)
47
- if key == :id
48
- @delegate.fetch(key) {
49
- @delegate[:id] = @by.send(:extract_session_id, @env)
50
- }
51
- else
52
- @delegate[key]
53
- end
49
+ @delegate[key]
50
+ end
51
+
52
+ def id(req)
53
+ @delegate.fetch(:id) {
54
+ @by.send(:extract_session_id, req)
55
+ }
54
56
  end
55
57
 
56
- def []=(k,v); @delegate[k] = v; end
58
+ def []=(k, v); @delegate[k] = v; end
57
59
  def to_hash; @delegate.dup; end
58
60
  def values_at(*args); @delegate.values_at(*args); end
59
61
  end
60
62
 
61
- def initialize(by, env)
63
+ def initialize(by, req)
62
64
  @by = by
63
- @env = env
65
+ @req = req
64
66
  @delegate = {}
65
67
  @loaded = false
66
- @exists = nil # we haven't checked yet
68
+ @exists = nil # We haven't checked yet.
67
69
  end
68
70
 
69
71
  def id
70
- options[:id]
72
+ options.id(@req)
71
73
  end
72
74
 
73
75
  def options
74
- Options.find @env
76
+ Options.find @req
75
77
  end
76
78
 
77
79
  def destroy
78
80
  clear
79
81
  options = self.options || {}
80
- new_sid = @by.send(:destroy_session, @env, options[:id], options)
81
- options[:id] = new_sid # Reset session id with a new value or nil
82
+ @by.send(:delete_session, @req, options.id(@req), options)
82
83
 
83
- # Load the new sid to be written with the response
84
+ # Load the new sid to be written with the response.
84
85
  @loaded = false
85
86
  load_for_write!
86
87
  end
87
88
 
89
+ # Returns value of the key stored in the session or
90
+ # +nil+ if the given key is not found in the session.
88
91
  def [](key)
89
92
  load_for_read!
90
- @delegate[key.to_s]
93
+ key = key.to_s
94
+
95
+ if key == "session_id"
96
+ id&.public_id
97
+ else
98
+ @delegate[key]
99
+ end
91
100
  end
92
101
 
102
+ # Returns the nested value specified by the sequence of keys, returning
103
+ # +nil+ if any intermediate step is +nil+.
104
+ def dig(*keys)
105
+ load_for_read!
106
+ keys = keys.map.with_index { |key, i| i.zero? ? key.to_s : key }
107
+ @delegate.dig(*keys)
108
+ end
109
+
110
+ # Returns true if the session has the given key or false.
93
111
  def has_key?(key)
94
112
  load_for_read!
95
113
  @delegate.key?(key.to_s)
@@ -97,40 +115,73 @@ module ActionDispatch
97
115
  alias :key? :has_key?
98
116
  alias :include? :has_key?
99
117
 
118
+ # Returns keys of the session as Array.
100
119
  def keys
120
+ load_for_read!
101
121
  @delegate.keys
102
122
  end
103
123
 
124
+ # Returns values of the session as Array.
104
125
  def values
126
+ load_for_read!
105
127
  @delegate.values
106
128
  end
107
129
 
130
+ # Writes given value to given key of the session.
108
131
  def []=(key, value)
109
132
  load_for_write!
110
133
  @delegate[key.to_s] = value
111
134
  end
112
135
 
136
+ # Clears the session.
113
137
  def clear
114
138
  load_for_write!
115
139
  @delegate.clear
116
140
  end
117
141
 
142
+ # Returns the session as Hash.
118
143
  def to_hash
119
144
  load_for_read!
120
- @delegate.dup.delete_if { |_,v| v.nil? }
121
- end
122
-
145
+ @delegate.dup.delete_if { |_, v| v.nil? }
146
+ end
147
+ alias :to_h :to_hash
148
+
149
+ # Updates the session with given Hash.
150
+ #
151
+ # session.to_hash
152
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"}
153
+ #
154
+ # session.update({ "foo" => "bar" })
155
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
156
+ #
157
+ # session.to_hash
158
+ # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"}
123
159
  def update(hash)
124
160
  load_for_write!
125
- @delegate.update stringify_keys(hash)
161
+ @delegate.update hash.stringify_keys
126
162
  end
127
163
 
164
+ # Deletes given key from the session.
128
165
  def delete(key)
129
166
  load_for_write!
130
167
  @delegate.delete key.to_s
131
168
  end
132
169
 
133
- def fetch(key, default=Unspecified, &block)
170
+ # Returns value of the given key from the session, or raises +KeyError+
171
+ # if can't find the given key and no default value is set.
172
+ # Returns default value if specified.
173
+ #
174
+ # session.fetch(:foo)
175
+ # # => KeyError: key not found: "foo"
176
+ #
177
+ # session.fetch(:foo, :bar)
178
+ # # => :bar
179
+ #
180
+ # session.fetch(:foo) do
181
+ # :bar
182
+ # end
183
+ # # => :bar
184
+ def fetch(key, default = Unspecified, &block)
134
185
  load_for_read!
135
186
  if default == Unspecified
136
187
  @delegate.fetch(key.to_s, &block)
@@ -149,7 +200,7 @@ module ActionDispatch
149
200
 
150
201
  def exists?
151
202
  return @exists unless @exists.nil?
152
- @exists = @by.send(:session_exists?, @env)
203
+ @exists = @by.send(:session_exists?, @req)
153
204
  end
154
205
 
155
206
  def loaded?
@@ -166,28 +217,25 @@ module ActionDispatch
166
217
  @delegate.merge!(other)
167
218
  end
168
219
 
169
- private
170
-
171
- def load_for_read!
172
- load! if !loaded? && exists?
220
+ def each(&block)
221
+ to_hash.each(&block)
173
222
  end
174
223
 
175
- def load_for_write!
176
- load! unless loaded?
177
- end
224
+ private
225
+ def load_for_read!
226
+ load! if !loaded? && exists?
227
+ end
178
228
 
179
- def load!
180
- id, session = @by.load_session @env
181
- options[:id] = id
182
- @delegate.replace(stringify_keys(session))
183
- @loaded = true
184
- end
229
+ def load_for_write!
230
+ load! unless loaded?
231
+ end
185
232
 
186
- def stringify_keys(other)
187
- other.each_with_object({}) { |(key, value), hash|
188
- hash[key.to_s] = value
189
- }
190
- end
233
+ def load!
234
+ id, session = @by.load_session @req
235
+ options[:id] = id
236
+ @delegate.replace(session.stringify_keys)
237
+ @loaded = true
238
+ end
191
239
  end
192
240
  end
193
241
  end