actionpack 4.2.11.1 → 6.0.3

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +212 -526
  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 +47 -50
  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 +59 -31
  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 +31 -30
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +42 -41
  16. data/lib/abstract_controller/translation.rb +12 -9
  17. data/lib/abstract_controller/url_for.rb +2 -0
  18. data/lib/abstract_controller.rb +12 -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 +25 -22
  22. data/lib/action_controller/caching.rb +13 -57
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +15 -17
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +124 -44
  27. data/lib/action_controller/metal/content_security_policy.rb +51 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +29 -49
  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 +20 -13
  33. data/lib/action_controller/metal/exceptions.rb +30 -15
  34. data/lib/action_controller/metal/flash.rb +9 -8
  35. data/lib/action_controller/metal/force_ssl.rb +23 -62
  36. data/lib/action_controller/metal/head.rb +22 -20
  37. data/lib/action_controller/metal/helpers.rb +26 -17
  38. data/lib/action_controller/metal/http_authentication.rb +76 -70
  39. data/lib/action_controller/metal/implicit_render.rb +53 -9
  40. data/lib/action_controller/metal/instrumentation.rb +22 -27
  41. data/lib/action_controller/metal/live.rb +101 -119
  42. data/lib/action_controller/metal/mime_responds.rb +44 -46
  43. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  44. data/lib/action_controller/metal/params_wrapper.rb +74 -63
  45. data/lib/action_controller/metal/redirecting.rb +53 -32
  46. data/lib/action_controller/metal/renderers.rb +87 -44
  47. data/lib/action_controller/metal/rendering.rb +72 -51
  48. data/lib/action_controller/metal/request_forgery_protection.rb +217 -97
  49. data/lib/action_controller/metal/rescue.rb +9 -16
  50. data/lib/action_controller/metal/streaming.rb +12 -11
  51. data/lib/action_controller/metal/strong_parameters.rb +619 -183
  52. data/lib/action_controller/metal/testing.rb +2 -17
  53. data/lib/action_controller/metal/url_for.rb +19 -10
  54. data/lib/action_controller/metal.rb +104 -87
  55. data/lib/action_controller/railtie.rb +28 -10
  56. data/lib/action_controller/railties/helpers.rb +3 -1
  57. data/lib/action_controller/renderer.rb +130 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +286 -418
  60. data/lib/action_controller.rb +33 -21
  61. data/lib/action_dispatch/http/cache.rb +100 -51
  62. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  63. data/lib/action_dispatch/http/content_security_policy.rb +282 -0
  64. data/lib/action_dispatch/http/filter_parameters.rb +31 -24
  65. data/lib/action_dispatch/http/filter_redirect.rb +10 -12
  66. data/lib/action_dispatch/http/headers.rb +54 -22
  67. data/lib/action_dispatch/http/mime_negotiation.rb +61 -45
  68. data/lib/action_dispatch/http/mime_type.rb +141 -122
  69. data/lib/action_dispatch/http/mime_types.rb +20 -6
  70. data/lib/action_dispatch/http/parameter_filter.rb +8 -68
  71. data/lib/action_dispatch/http/parameters.rb +107 -39
  72. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  73. data/lib/action_dispatch/http/request.rb +204 -117
  74. data/lib/action_dispatch/http/response.rb +248 -114
  75. data/lib/action_dispatch/http/upload.rb +21 -7
  76. data/lib/action_dispatch/http/url.rb +181 -100
  77. data/lib/action_dispatch/journey/formatter.rb +56 -34
  78. data/lib/action_dispatch/journey/gtg/builder.rb +7 -6
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -17
  81. data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
  82. data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +3 -3
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -49
  85. data/lib/action_dispatch/journey/nodes/node.rb +25 -12
  86. data/lib/action_dispatch/journey/parser.rb +23 -22
  87. data/lib/action_dispatch/journey/parser.y +3 -2
  88. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  89. data/lib/action_dispatch/journey/path/pattern.rb +55 -46
  90. data/lib/action_dispatch/journey/route.rb +107 -28
  91. data/lib/action_dispatch/journey/router/utils.rb +25 -16
  92. data/lib/action_dispatch/journey/router.rb +35 -27
  93. data/lib/action_dispatch/journey/routes.rb +17 -17
  94. data/lib/action_dispatch/journey/scanner.rb +26 -17
  95. data/lib/action_dispatch/journey/visitors.rb +98 -54
  96. data/lib/action_dispatch/journey.rb +7 -5
  97. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +3 -6
  99. data/lib/action_dispatch/middleware/cookies.rb +292 -203
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +142 -63
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  103. data/lib/action_dispatch/middleware/exception_wrapper.rb +102 -70
  104. data/lib/action_dispatch/middleware/executor.rb +21 -0
  105. data/lib/action_dispatch/middleware/flash.rb +78 -54
  106. data/lib/action_dispatch/middleware/host_authorization.rb +101 -0
  107. data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
  108. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  109. data/lib/action_dispatch/middleware/remote_ip.rb +48 -41
  110. data/lib/action_dispatch/middleware/request_id.rb +17 -9
  111. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
  112. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  113. data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -73
  114. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  115. data/lib/action_dispatch/middleware/show_exceptions.rb +26 -23
  116. data/lib/action_dispatch/middleware/ssl.rb +113 -35
  117. data/lib/action_dispatch/middleware/stack.rb +64 -41
  118. data/lib/action_dispatch/middleware/static.rb +57 -51
  119. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -14
  122. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  123. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
  124. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  126. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  130. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +5 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  136. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  138. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.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 +67 -64
  141. data/lib/action_dispatch/railtie.rb +26 -13
  142. data/lib/action_dispatch/request/session.rb +114 -60
  143. data/lib/action_dispatch/request/utils.rb +67 -24
  144. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  145. data/lib/action_dispatch/routing/inspector.rb +140 -102
  146. data/lib/action_dispatch/routing/mapper.rb +762 -455
  147. data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -142
  148. data/lib/action_dispatch/routing/redirection.rb +36 -26
  149. data/lib/action_dispatch/routing/route_set.rb +322 -298
  150. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  151. data/lib/action_dispatch/routing/url_for.rb +65 -26
  152. data/lib/action_dispatch/routing.rb +36 -36
  153. data/lib/action_dispatch/system_test_case.rb +185 -0
  154. data/lib/action_dispatch/system_testing/browser.rb +80 -0
  155. data/lib/action_dispatch/system_testing/driver.rb +68 -0
  156. data/lib/action_dispatch/system_testing/server.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +97 -0
  158. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +32 -0
  159. data/lib/action_dispatch/testing/assertion_response.rb +46 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +44 -20
  161. data/lib/action_dispatch/testing/assertions/routing.rb +44 -28
  162. data/lib/action_dispatch/testing/assertions.rb +6 -4
  163. data/lib/action_dispatch/testing/integration.rb +375 -215
  164. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  165. data/lib/action_dispatch/testing/test_process.rb +28 -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 +33 -20
  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 +71 -40
  173. data/lib/action_controller/metal/hide_actions.rb +0 -40
  174. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  175. data/lib/action_controller/middleware.rb +0 -39
  176. data/lib/action_controller/model_naming.rb +0 -12
  177. data/lib/action_dispatch/journey/backwards.rb +0 -5
  178. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  179. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  180. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  181. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  182. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,9 +1,12 @@
1
- require 'securerandom'
2
- require 'active_support/core_ext/string/access'
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+ require "active_support/core_ext/string/access"
3
5
 
4
6
  module ActionDispatch
5
- # Makes a unique request id available to the action_dispatch.request_id env variable (which is then accessible through
6
- # ActionDispatch::Request#uuid) and sends the same id to the client via the X-Request-Id header.
7
+ # Makes a unique request id available to the +action_dispatch.request_id+ env variable (which is then accessible
8
+ # through <tt>ActionDispatch::Request#request_id</tt> or the alias <tt>ActionDispatch::Request#uuid</tt>) and sends
9
+ # the same id to the client via the X-Request-Id header.
7
10
  #
8
11
  # The unique request id is either based on the X-Request-Id header in the request, which would typically be generated
9
12
  # by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the
@@ -12,19 +15,24 @@ module ActionDispatch
12
15
  # The unique request id can be used to trace a request end-to-end and would typically end up being part of log files
13
16
  # from multiple pieces of the stack.
14
17
  class RequestId
18
+ X_REQUEST_ID = "X-Request-Id" #:nodoc:
19
+
15
20
  def initialize(app)
16
21
  @app = app
17
22
  end
18
23
 
19
24
  def call(env)
20
- env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id
21
- @app.call(env).tap { |_status, headers, _body| headers["X-Request-Id"] = env["action_dispatch.request_id"] }
25
+ req = ActionDispatch::Request.new env
26
+ req.request_id = make_request_id(req.x_request_id)
27
+ @app.call(env).tap { |_status, headers, _body| headers[X_REQUEST_ID] = req.request_id }
22
28
  end
23
29
 
24
30
  private
25
- def external_request_id(env)
26
- if request_id = env["HTTP_X_REQUEST_ID"].presence
27
- request_id.gsub(/[^\w\-]/, "").first(255)
31
+ def make_request_id(request_id)
32
+ if request_id.presence
33
+ request_id.gsub(/[^\w\-@]/, "").first(255)
34
+ else
35
+ internal_request_id
28
36
  end
29
37
  end
30
38
 
@@ -1,26 +1,25 @@
1
- require 'rack/utils'
2
- require 'rack/request'
3
- require 'rack/session/abstract/id'
4
- require 'action_dispatch/middleware/cookies'
5
- require 'action_dispatch/request/session'
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/utils"
4
+ require "rack/request"
5
+ require "rack/session/abstract/id"
6
+ require "action_dispatch/middleware/cookies"
7
+ require "action_dispatch/request/session"
6
8
 
7
9
  module ActionDispatch
8
10
  module Session
9
11
  class SessionRestoreError < StandardError #:nodoc:
10
- attr_reader :original_exception
11
-
12
- def initialize(const_error)
13
- @original_exception = const_error
14
-
15
- super("Session contains objects whose class definition isn't available.\n" +
16
- "Remember to require the classes for all objects kept in the session.\n" +
17
- "(Original exception: #{const_error.message} [#{const_error.class}])\n")
12
+ def initialize
13
+ super("Session contains objects whose class definition isn't available.\n" \
14
+ "Remember to require the classes for all objects kept in the session.\n" \
15
+ "(Original exception: #{$!.message} [#{$!.class}])\n")
16
+ set_backtrace $!.backtrace
18
17
  end
19
18
  end
20
19
 
21
20
  module Compatibility
22
21
  def initialize(app, options = {})
23
- options[:key] ||= '_session_id'
22
+ options[:key] ||= "_session_id"
24
23
  super
25
24
  end
26
25
 
@@ -30,12 +29,15 @@ module ActionDispatch
30
29
  sid
31
30
  end
32
31
 
33
- protected
34
-
35
- def initialize_sid
32
+ private
33
+ def initialize_sid # :doc:
36
34
  @default_options.delete(:sidbits)
37
35
  @default_options.delete(:secure_random)
38
36
  end
37
+
38
+ def make_request(env)
39
+ ActionDispatch::Request.new env
40
+ end
39
41
  end
40
42
 
41
43
  module StaleSessionCheck
@@ -52,10 +54,10 @@ module ActionDispatch
52
54
  rescue ArgumentError => argument_error
53
55
  if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
54
56
  begin
55
- # Note that the regexp does not allow $1 to end with a ':'
57
+ # Note that the regexp does not allow $1 to end with a ':'.
56
58
  $1.constantize
57
- rescue LoadError, NameError => e
58
- raise ActionDispatch::Session::SessionRestoreError, e, e.backtrace
59
+ rescue LoadError, NameError
60
+ raise ActionDispatch::Session::SessionRestoreError
59
61
  end
60
62
  retry
61
63
  else
@@ -65,8 +67,8 @@ module ActionDispatch
65
67
  end
66
68
 
67
69
  module SessionObject # :nodoc:
68
- def prepare_session(env)
69
- Request::Session.create(self, env, @default_options)
70
+ def prepare_session(req)
71
+ Request::Session.create(self, req, @default_options)
70
72
  end
71
73
 
72
74
  def loaded_session?(session)
@@ -74,17 +76,30 @@ module ActionDispatch
74
76
  end
75
77
  end
76
78
 
77
- class AbstractStore < Rack::Session::Abstract::ID
79
+ class AbstractStore < Rack::Session::Abstract::Persisted
78
80
  include Compatibility
79
81
  include StaleSessionCheck
80
82
  include SessionObject
81
83
 
82
84
  private
85
+ def set_cookie(request, session_id, cookie)
86
+ request.cookie_jar[key] = cookie
87
+ end
88
+ end
83
89
 
84
- def set_cookie(env, session_id, cookie)
85
- request = ActionDispatch::Request.new(env)
86
- request.cookie_jar[key] = cookie
90
+ class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure
91
+ include Compatibility
92
+ include StaleSessionCheck
93
+ include SessionObject
94
+
95
+ def generate_sid
96
+ Rack::Session::SessionId.new(super)
87
97
  end
98
+
99
+ private
100
+ def set_cookie(request, session_id, cookie)
101
+ request.cookie_jar[key] = cookie
102
+ end
88
103
  end
89
104
  end
90
105
  end
@@ -1,13 +1,18 @@
1
- require 'action_dispatch/middleware/session/abstract_store'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_dispatch/middleware/session/abstract_store"
2
4
 
3
5
  module ActionDispatch
4
6
  module Session
5
- # Session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful
7
+ # A session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful
6
8
  # if you don't store critical data in your sessions and you don't need them to live for extended periods
7
9
  # of time.
8
- class CacheStore < AbstractStore
9
- # Create a new store. The cache to use can be passed in the <tt>:cache</tt> option. If it is
10
- # not specified, <tt>Rails.cache</tt> will be used.
10
+ #
11
+ # ==== Options
12
+ # * <tt>cache</tt> - The cache to use. If it is not specified, <tt>Rails.cache</tt> will be used.
13
+ # * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
14
+ # By default, the <tt>:expires_in</tt> option of the cache is used.
15
+ class CacheStore < AbstractSecureStore
11
16
  def initialize(app, options = {})
12
17
  @cache = options[:cache] || Rails.cache
13
18
  options[:expire_after] ||= @cache.options[:expires_in]
@@ -15,18 +20,18 @@ module ActionDispatch
15
20
  end
16
21
 
17
22
  # Get a session from the cache.
18
- def get_session(env, sid)
19
- unless sid and session = @cache.read(cache_key(sid))
23
+ def find_session(env, sid)
24
+ unless sid && (session = get_session_with_fallback(sid))
20
25
  sid, session = generate_sid, {}
21
26
  end
22
27
  [sid, session]
23
28
  end
24
29
 
25
30
  # Set a session in the cache.
26
- def set_session(env, sid, session, options)
27
- key = cache_key(sid)
31
+ def write_session(env, sid, session, options)
32
+ key = cache_key(sid.private_id)
28
33
  if session
29
- @cache.write(key, session, :expires_in => options[:expire_after])
34
+ @cache.write(key, session, expires_in: options[:expire_after])
30
35
  else
31
36
  @cache.delete(key)
32
37
  end
@@ -34,15 +39,20 @@ module ActionDispatch
34
39
  end
35
40
 
36
41
  # Remove a session from the cache.
37
- def destroy_session(env, sid, options)
38
- @cache.delete(cache_key(sid))
42
+ def delete_session(env, sid, options)
43
+ @cache.delete(cache_key(sid.private_id))
44
+ @cache.delete(cache_key(sid.public_id))
39
45
  generate_sid
40
46
  end
41
47
 
42
48
  private
43
49
  # Turn the session id into a cache key.
44
- def cache_key(sid)
45
- "_session_id:#{sid}"
50
+ def cache_key(id)
51
+ "_session_id:#{id}"
52
+ end
53
+
54
+ def get_session_with_fallback(sid)
55
+ @cache.read(cache_key(sid.private_id)) || @cache.read(cache_key(sid.public_id))
46
56
  end
47
57
  end
48
58
  end
@@ -1,6 +1,8 @@
1
- require 'active_support/core_ext/hash/keys'
2
- require 'action_dispatch/middleware/session/abstract_store'
3
- require 'rack/session/cookie'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+ require "action_dispatch/middleware/session/abstract_store"
5
+ require "rack/session/cookie"
4
6
 
5
7
  module ActionDispatch
6
8
  module Session
@@ -14,110 +16,107 @@ module ActionDispatch
14
16
  # The cookie jar used for storage is automatically configured to be the
15
17
  # best possible option given your application's configuration.
16
18
  #
17
- # If you only have secret_token set, your cookies will be signed, but
18
- # not encrypted. This means a user cannot alter their +user_id+ without
19
- # knowing your app's secret key, but can easily read their +user_id+. This
20
- # was the default for Rails 3 apps.
21
- #
22
- # If you have secret_key_base set, your cookies will be encrypted. This
19
+ # Your cookies will be encrypted using your apps secret_key_base. This
23
20
  # goes a step further than signed cookies in that encrypted cookies cannot
24
21
  # be altered or read by users. This is the default starting in Rails 4.
25
22
  #
26
- # If you have both secret_token and secret_key base set, your cookies will
27
- # be encrypted, and signed cookies generated by Rails 3 will be
28
- # transparently read and encrypted to provide a smooth upgrade path.
29
- #
30
- # Configure your session store in config/initializers/session_store.rb:
23
+ # Configure your session store in an initializer:
31
24
  #
32
25
  # Rails.application.config.session_store :cookie_store, key: '_your_app_session'
33
26
  #
34
- # Configure your secret key in config/secrets.yml:
27
+ # In the development and test environments your application's secret key base is
28
+ # generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
29
+ # In all other environments, it is stored encrypted in the
30
+ # <tt>config/credentials.yml.enc</tt> file.
35
31
  #
36
- # development:
37
- # secret_key_base: 'secret key'
32
+ # If your application was not updated to Rails 5.2 defaults, the secret_key_base
33
+ # will be found in the old <tt>config/secrets.yml</tt> file.
38
34
  #
39
- # To generate a secret key for an existing application, run `rake secret`.
35
+ # Note that changing your secret_key_base will invalidate all existing session.
36
+ # Additionally, you should take care to make sure you are not relying on the
37
+ # ability to decode signed cookies generated by your app in external
38
+ # applications or JavaScript before changing it.
40
39
  #
41
- # If you are upgrading an existing Rails 3 app, you should leave your
42
- # existing secret_token in place and simply add the new secret_key_base.
43
- # Note that you should wait to set secret_key_base until you have 100% of
44
- # your userbase on Rails 4 and are reasonably sure you will not need to
45
- # rollback to Rails 3. This is because cookies signed based on the new
46
- # secret_key_base in Rails 4 are not backwards compatible with Rails 3.
47
- # You are free to leave your existing secret_token in place, not set the
48
- # new secret_key_base, and ignore the deprecation warnings until you are
49
- # reasonably sure that your upgrade is otherwise complete. Additionally,
50
- # you should take care to make sure you are not relying on the ability to
51
- # decode signed cookies generated by your app in external applications or
52
- # JavaScript before upgrading.
40
+ # Because CookieStore extends Rack::Session::Abstract::Persisted, many of the
41
+ # options described there can be used to customize the session cookie that
42
+ # is generated. For example:
53
43
  #
54
- # Note that changing the secret key will invalidate all existing sessions!
55
- class CookieStore < Rack::Session::Abstract::ID
56
- include Compatibility
57
- include StaleSessionCheck
58
- include SessionObject
44
+ # Rails.application.config.session_store :cookie_store, expire_after: 14.days
45
+ #
46
+ # would set the session cookie to expire automatically 14 days after creation.
47
+ # Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
48
+ # <tt>:httponly</tt>.
49
+ class CookieStore < AbstractSecureStore
50
+ class SessionId < DelegateClass(Rack::Session::SessionId)
51
+ attr_reader :cookie_value
52
+
53
+ def initialize(session_id, cookie_value = {})
54
+ super(session_id)
55
+ @cookie_value = cookie_value
56
+ end
57
+ end
59
58
 
60
- def initialize(app, options={})
61
- super(app, options.merge!(:cookie_only => true))
59
+ def initialize(app, options = {})
60
+ super(app, options.merge!(cookie_only: true))
62
61
  end
63
62
 
64
- def destroy_session(env, session_id, options)
63
+ def delete_session(req, session_id, options)
65
64
  new_sid = generate_sid unless options[:drop]
66
65
  # Reset hash and Assign the new session id
67
- env["action_dispatch.request.unsigned_session_cookie"] = new_sid ? { "session_id" => new_sid } : {}
66
+ req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
68
67
  new_sid
69
68
  end
70
69
 
71
- def load_session(env)
70
+ def load_session(req)
72
71
  stale_session_check! do
73
- data = unpacked_cookie_data(env)
72
+ data = unpacked_cookie_data(req)
74
73
  data = persistent_session_id!(data)
75
- [data["session_id"], data]
74
+ [Rack::Session::SessionId.new(data["session_id"]), data]
76
75
  end
77
76
  end
78
77
 
79
78
  private
80
-
81
- def extract_session_id(env)
82
- stale_session_check! do
83
- unpacked_cookie_data(env)["session_id"]
79
+ def extract_session_id(req)
80
+ stale_session_check! do
81
+ sid = unpacked_cookie_data(req)["session_id"]
82
+ sid && Rack::Session::SessionId.new(sid)
83
+ end
84
84
  end
85
- end
86
85
 
87
- def unpacked_cookie_data(env)
88
- env["action_dispatch.request.unsigned_session_cookie"] ||= begin
89
- stale_session_check! do
90
- if data = get_cookie(env)
91
- data.stringify_keys!
86
+ def unpacked_cookie_data(req)
87
+ req.fetch_header("action_dispatch.request.unsigned_session_cookie") do |k|
88
+ v = stale_session_check! do
89
+ if data = get_cookie(req)
90
+ data.stringify_keys!
91
+ end
92
+ data || {}
92
93
  end
93
- data || {}
94
+ req.set_header k, v
94
95
  end
95
96
  end
96
- end
97
97
 
98
- def persistent_session_id!(data, sid=nil)
99
- data ||= {}
100
- data["session_id"] ||= sid || generate_sid
101
- data
102
- end
98
+ def persistent_session_id!(data, sid = nil)
99
+ data ||= {}
100
+ data["session_id"] ||= sid || generate_sid.public_id
101
+ data
102
+ end
103
103
 
104
- def set_session(env, sid, session_data, options)
105
- session_data["session_id"] = sid
106
- session_data
107
- end
104
+ def write_session(req, sid, session_data, options)
105
+ session_data["session_id"] = sid.public_id
106
+ SessionId.new(sid, session_data)
107
+ end
108
108
 
109
- def set_cookie(env, session_id, cookie)
110
- cookie_jar(env)[@key] = cookie
111
- end
109
+ def set_cookie(request, session_id, cookie)
110
+ cookie_jar(request)[@key] = cookie
111
+ end
112
112
 
113
- def get_cookie(env)
114
- cookie_jar(env)[@key]
115
- end
113
+ def get_cookie(req)
114
+ cookie_jar(req)[@key]
115
+ end
116
116
 
117
- def cookie_jar(env)
118
- request = ActionDispatch::Request.new(env)
119
- request.cookie_jar.signed_or_encrypted
120
- end
117
+ def cookie_jar(request)
118
+ request.cookie_jar.signed_or_encrypted
119
+ end
121
120
  end
122
121
  end
123
122
  end
@@ -1,6 +1,8 @@
1
- require 'action_dispatch/middleware/session/abstract_store'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_dispatch/middleware/session/abstract_store"
2
4
  begin
3
- require 'rack/session/dalli'
5
+ require "rack/session/dalli"
4
6
  rescue LoadError => e
5
7
  $stderr.puts "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
6
8
  raise e
@@ -8,6 +10,10 @@ end
8
10
 
9
11
  module ActionDispatch
10
12
  module Session
13
+ # A session store that uses MemCache to implement storage.
14
+ #
15
+ # ==== Options
16
+ # * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
11
17
  class MemCacheStore < Rack::Session::Dalli
12
18
  include Compatibility
13
19
  include StaleSessionCheck
@@ -1,5 +1,7 @@
1
- require 'action_dispatch/http/request'
2
- require 'action_dispatch/middleware/exception_wrapper'
1
+ # frozen_string_literal: true
2
+
3
+ require "action_dispatch/http/request"
4
+ require "action_dispatch/middleware/exception_wrapper"
3
5
 
4
6
  module ActionDispatch
5
7
  # This middleware rescues any exception returned by the application
@@ -8,14 +10,14 @@ module ActionDispatch
8
10
  # The exceptions app should be passed as parameter on initialization
9
11
  # of ShowExceptions. Every time there is an exception, ShowExceptions will
10
12
  # store the exception in env["action_dispatch.exception"], rewrite the
11
- # PATH_INFO to the exception status code and call the rack app.
13
+ # PATH_INFO to the exception status code and call the Rack app.
12
14
  #
13
15
  # If the application returns a "X-Cascade" pass response, this middleware
14
16
  # will send an empty response as result with the correct status code.
15
17
  # If any exception happens inside the exceptions app, this middleware
16
18
  # catches the exceptions and returns a FAILSAFE_RESPONSE.
17
19
  class ShowExceptions
18
- FAILSAFE_RESPONSE = [500, { 'Content-Type' => 'text/plain' },
20
+ FAILSAFE_RESPONSE = [500, { "Content-Type" => "text/plain" },
19
21
  ["500 Internal Server Error\n" \
20
22
  "If you are the administrator of this website, then please read this web " \
21
23
  "application's log file and/or the web server's log file to find out what " \
@@ -27,32 +29,33 @@ module ActionDispatch
27
29
  end
28
30
 
29
31
  def call(env)
32
+ request = ActionDispatch::Request.new env
30
33
  @app.call(env)
31
34
  rescue Exception => exception
32
- if env['action_dispatch.show_exceptions'] == false
33
- raise exception
35
+ if request.show_exceptions?
36
+ render_exception(request, exception)
34
37
  else
35
- render_exception(env, exception)
38
+ raise exception
36
39
  end
37
40
  end
38
41
 
39
42
  private
43
+ def render_exception(request, exception)
44
+ backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
45
+ wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
46
+ status = wrapper.status_code
47
+ request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
48
+ request.set_header "action_dispatch.original_path", request.path_info
49
+ request.path_info = "/#{status}"
50
+ response = @exceptions_app.call(request.env)
51
+ response[1]["X-Cascade"] == "pass" ? pass_response(status) : response
52
+ rescue Exception => failsafe_error
53
+ $stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
54
+ FAILSAFE_RESPONSE
55
+ end
40
56
 
41
- def render_exception(env, exception)
42
- wrapper = ExceptionWrapper.new(env, exception)
43
- status = wrapper.status_code
44
- env["action_dispatch.exception"] = wrapper.exception
45
- env["action_dispatch.original_path"] = env["PATH_INFO"]
46
- env["PATH_INFO"] = "/#{status}"
47
- response = @exceptions_app.call(env)
48
- response[1]['X-Cascade'] == 'pass' ? pass_response(status) : response
49
- rescue Exception => failsafe_error
50
- $stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
51
- FAILSAFE_RESPONSE
52
- end
53
-
54
- def pass_response(status)
55
- [status, {"Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0"}, []]
56
- end
57
+ def pass_response(status)
58
+ [status, { "Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0" }, []]
59
+ end
57
60
  end
58
61
  end