actionpack 4.2.8 → 5.2.4.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 (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +285 -444
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -7
  5. data/lib/abstract_controller.rb +12 -5
  6. data/lib/abstract_controller/asset_paths.rb +2 -0
  7. data/lib/abstract_controller/base.rb +45 -49
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +78 -15
  10. data/lib/abstract_controller/callbacks.rb +47 -31
  11. data/lib/abstract_controller/collector.rb +8 -11
  12. data/lib/abstract_controller/error.rb +6 -0
  13. data/lib/abstract_controller/helpers.rb +25 -25
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +4 -2
  16. data/lib/abstract_controller/rendering.rb +42 -41
  17. data/lib/abstract_controller/translation.rb +10 -7
  18. data/lib/abstract_controller/url_for.rb +2 -0
  19. data/lib/action_controller.rb +29 -21
  20. data/lib/action_controller/api.rb +149 -0
  21. data/lib/action_controller/api/api_rendering.rb +16 -0
  22. data/lib/action_controller/base.rb +27 -19
  23. data/lib/action_controller/caching.rb +14 -57
  24. data/lib/action_controller/form_builder.rb +50 -0
  25. data/lib/action_controller/log_subscriber.rb +10 -15
  26. data/lib/action_controller/metal.rb +98 -83
  27. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  28. data/lib/action_controller/metal/conditional_get.rb +118 -44
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +3 -3
  31. data/lib/action_controller/metal/data_streaming.rb +27 -46
  32. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
  34. data/lib/action_controller/metal/exceptions.rb +8 -14
  35. data/lib/action_controller/metal/flash.rb +4 -3
  36. data/lib/action_controller/metal/force_ssl.rb +23 -21
  37. data/lib/action_controller/metal/head.rb +21 -19
  38. data/lib/action_controller/metal/helpers.rb +24 -14
  39. data/lib/action_controller/metal/http_authentication.rb +64 -57
  40. data/lib/action_controller/metal/implicit_render.rb +62 -8
  41. data/lib/action_controller/metal/instrumentation.rb +19 -21
  42. data/lib/action_controller/metal/live.rb +90 -106
  43. data/lib/action_controller/metal/mime_responds.rb +33 -46
  44. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +61 -53
  46. data/lib/action_controller/metal/redirecting.rb +49 -28
  47. data/lib/action_controller/metal/renderers.rb +87 -44
  48. data/lib/action_controller/metal/rendering.rb +72 -50
  49. data/lib/action_controller/metal/request_forgery_protection.rb +203 -92
  50. data/lib/action_controller/metal/rescue.rb +9 -16
  51. data/lib/action_controller/metal/streaming.rb +12 -10
  52. data/lib/action_controller/metal/strong_parameters.rb +582 -165
  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/railtie.rb +28 -10
  56. data/lib/action_controller/railties/helpers.rb +2 -0
  57. data/lib/action_controller/renderer.rb +117 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +280 -411
  60. data/lib/action_dispatch.rb +27 -19
  61. data/lib/action_dispatch/http/cache.rb +93 -47
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +26 -20
  64. data/lib/action_dispatch/http/filter_redirect.rb +10 -11
  65. data/lib/action_dispatch/http/headers.rb +55 -22
  66. data/lib/action_dispatch/http/mime_negotiation.rb +60 -41
  67. data/lib/action_dispatch/http/mime_type.rb +134 -121
  68. data/lib/action_dispatch/http/mime_types.rb +20 -6
  69. data/lib/action_dispatch/http/parameter_filter.rb +25 -11
  70. data/lib/action_dispatch/http/parameters.rb +98 -39
  71. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  72. data/lib/action_dispatch/http/request.rb +200 -118
  73. data/lib/action_dispatch/http/response.rb +225 -110
  74. data/lib/action_dispatch/http/upload.rb +12 -6
  75. data/lib/action_dispatch/http/url.rb +110 -28
  76. data/lib/action_dispatch/journey.rb +7 -5
  77. data/lib/action_dispatch/journey/formatter.rb +55 -32
  78. data/lib/action_dispatch/journey/gtg/builder.rb +7 -5
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -16
  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 -1
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -48
  85. data/lib/action_dispatch/journey/nodes/node.rb +18 -6
  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 +50 -44
  90. data/lib/action_dispatch/journey/route.rb +106 -28
  91. data/lib/action_dispatch/journey/router.rb +35 -23
  92. data/lib/action_dispatch/journey/router/utils.rb +20 -11
  93. data/lib/action_dispatch/journey/routes.rb +18 -16
  94. data/lib/action_dispatch/journey/scanner.rb +18 -15
  95. data/lib/action_dispatch/journey/visitors.rb +99 -52
  96. data/lib/action_dispatch/middleware/callbacks.rb +1 -2
  97. data/lib/action_dispatch/middleware/cookies.rb +304 -193
  98. data/lib/action_dispatch/middleware/debug_exceptions.rb +152 -57
  99. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  100. data/lib/action_dispatch/middleware/exception_wrapper.rb +68 -69
  101. data/lib/action_dispatch/middleware/executor.rb +21 -0
  102. data/lib/action_dispatch/middleware/flash.rb +78 -54
  103. data/lib/action_dispatch/middleware/public_exceptions.rb +27 -25
  104. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  105. data/lib/action_dispatch/middleware/remote_ip.rb +41 -31
  106. data/lib/action_dispatch/middleware/request_id.rb +17 -9
  107. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -25
  108. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  109. data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -67
  110. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  111. data/lib/action_dispatch/middleware/show_exceptions.rb +26 -22
  112. data/lib/action_dispatch/middleware/ssl.rb +114 -36
  113. data/lib/action_dispatch/middleware/stack.rb +31 -44
  114. data/lib/action_dispatch/middleware/static.rb +57 -50
  115. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
  116. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  119. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  123. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  124. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -64
  125. data/lib/action_dispatch/railtie.rb +19 -11
  126. data/lib/action_dispatch/request/session.rb +106 -59
  127. data/lib/action_dispatch/request/utils.rb +67 -24
  128. data/lib/action_dispatch/routing.rb +17 -18
  129. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  130. data/lib/action_dispatch/routing/inspector.rb +58 -67
  131. data/lib/action_dispatch/routing/mapper.rb +734 -447
  132. data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -139
  133. data/lib/action_dispatch/routing/redirection.rb +36 -26
  134. data/lib/action_dispatch/routing/route_set.rb +321 -291
  135. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  136. data/lib/action_dispatch/routing/url_for.rb +65 -25
  137. data/lib/action_dispatch/system_test_case.rb +147 -0
  138. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  139. data/lib/action_dispatch/system_testing/driver.rb +59 -0
  140. data/lib/action_dispatch/system_testing/server.rb +31 -0
  141. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
  142. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
  143. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  144. data/lib/action_dispatch/testing/assertion_response.rb +47 -0
  145. data/lib/action_dispatch/testing/assertions.rb +6 -4
  146. data/lib/action_dispatch/testing/assertions/response.rb +45 -20
  147. data/lib/action_dispatch/testing/assertions/routing.rb +30 -26
  148. data/lib/action_dispatch/testing/integration.rb +347 -209
  149. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  150. data/lib/action_dispatch/testing/test_process.rb +28 -22
  151. data/lib/action_dispatch/testing/test_request.rb +27 -34
  152. data/lib/action_dispatch/testing/test_response.rb +35 -7
  153. data/lib/action_pack.rb +4 -2
  154. data/lib/action_pack/gem_version.rb +5 -3
  155. data/lib/action_pack/version.rb +3 -1
  156. metadata +56 -39
  157. data/lib/action_controller/metal/hide_actions.rb +0 -40
  158. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  159. data/lib/action_controller/middleware.rb +0 -39
  160. data/lib/action_controller/model_naming.rb +0 -12
  161. data/lib/action_dispatch/journey/backwards.rb +0 -5
  162. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  163. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  164. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  165. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  166. 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".freeze #: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\-@]/, "".freeze).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,16 @@ module ActionDispatch
30
29
  sid
31
30
  end
32
31
 
33
- protected
32
+ private
34
33
 
35
- def initialize_sid
34
+ def initialize_sid # :doc:
36
35
  @default_options.delete(:sidbits)
37
36
  @default_options.delete(:secure_random)
38
37
  end
38
+
39
+ def make_request(env)
40
+ ActionDispatch::Request.new env
41
+ end
39
42
  end
40
43
 
41
44
  module StaleSessionCheck
@@ -52,10 +55,10 @@ module ActionDispatch
52
55
  rescue ArgumentError => argument_error
53
56
  if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
54
57
  begin
55
- # Note that the regexp does not allow $1 to end with a ':'
58
+ # Note that the regexp does not allow $1 to end with a ':'.
56
59
  $1.constantize
57
- rescue LoadError, NameError => e
58
- raise ActionDispatch::Session::SessionRestoreError, e, e.backtrace
60
+ rescue LoadError, NameError
61
+ raise ActionDispatch::Session::SessionRestoreError
59
62
  end
60
63
  retry
61
64
  else
@@ -65,8 +68,8 @@ module ActionDispatch
65
68
  end
66
69
 
67
70
  module SessionObject # :nodoc:
68
- def prepare_session(env)
69
- Request::Session.create(self, env, @default_options)
71
+ def prepare_session(req)
72
+ Request::Session.create(self, req, @default_options)
70
73
  end
71
74
 
72
75
  def loaded_session?(session)
@@ -74,17 +77,30 @@ module ActionDispatch
74
77
  end
75
78
  end
76
79
 
77
- class AbstractStore < Rack::Session::Abstract::ID
80
+ class AbstractStore < Rack::Session::Abstract::Persisted
78
81
  include Compatibility
79
82
  include StaleSessionCheck
80
83
  include SessionObject
81
84
 
82
85
  private
86
+ def set_cookie(request, session_id, cookie)
87
+ request.cookie_jar[key] = cookie
88
+ end
89
+ end
83
90
 
84
- def set_cookie(env, session_id, cookie)
85
- request = ActionDispatch::Request.new(env)
86
- request.cookie_jar[key] = cookie
91
+ class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure
92
+ include Compatibility
93
+ include StaleSessionCheck
94
+ include SessionObject
95
+
96
+ def generate_sid
97
+ Rack::Session::SessionId.new(super)
87
98
  end
99
+
100
+ private
101
+ def set_cookie(request, session_id, cookie)
102
+ request.cookie_jar[key] = cookie
103
+ end
88
104
  end
89
105
  end
90
106
  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
@@ -19,105 +21,108 @@ module ActionDispatch
19
21
  # knowing your app's secret key, but can easily read their +user_id+. This
20
22
  # was the default for Rails 3 apps.
21
23
  #
22
- # If you have secret_key_base set, your cookies will be encrypted. This
24
+ # Your cookies will be encrypted using your apps secret_key_base. This
23
25
  # goes a step further than signed cookies in that encrypted cookies cannot
24
26
  # be altered or read by users. This is the default starting in Rails 4.
25
27
  #
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:
28
+ # Configure your session store in <tt>config/initializers/session_store.rb</tt>:
31
29
  #
32
30
  # Rails.application.config.session_store :cookie_store, key: '_your_app_session'
33
31
  #
34
- # Configure your secret key in config/secrets.yml:
32
+ # In the development and test environments your application's secret key base is
33
+ # generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
34
+ # In all other environments, it is stored encrypted in the
35
+ # <tt>config/credentials.yml.enc</tt> file.
36
+ #
37
+ # If your application was not updated to Rails 5.2 defaults, the secret_key_base
38
+ # will be found in the old <tt>config/secrets.yml</tt> file.
35
39
  #
36
- # development:
37
- # secret_key_base: 'secret key'
40
+ # Note that changing your secret_key_base will invalidate all existing session.
41
+ # Additionally, you should take care to make sure you are not relying on the
42
+ # ability to decode signed cookies generated by your app in external
43
+ # applications or JavaScript before changing it.
38
44
  #
39
- # To generate a secret key for an existing application, run `rake secret`.
45
+ # Because CookieStore extends Rack::Session::Abstract::Persisted, many of the
46
+ # options described there can be used to customize the session cookie that
47
+ # is generated. For example:
40
48
  #
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.
49
+ # Rails.application.config.session_store :cookie_store, expire_after: 14.days
53
50
  #
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
51
+ # would set the session cookie to expire automatically 14 days after creation.
52
+ # Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
53
+ # <tt>:httponly</tt>.
54
+ class CookieStore < AbstractSecureStore
55
+ class SessionId < DelegateClass(Rack::Session::SessionId)
56
+ attr_reader :cookie_value
57
+
58
+ def initialize(session_id, cookie_value = {})
59
+ super(session_id)
60
+ @cookie_value = cookie_value
61
+ end
62
+ end
59
63
 
60
- def initialize(app, options={})
61
- super(app, options.merge!(:cookie_only => true))
64
+ def initialize(app, options = {})
65
+ super(app, options.merge!(cookie_only: true))
62
66
  end
63
67
 
64
- def destroy_session(env, session_id, options)
68
+ def delete_session(req, session_id, options)
65
69
  new_sid = generate_sid unless options[:drop]
66
70
  # Reset hash and Assign the new session id
67
- env["action_dispatch.request.unsigned_session_cookie"] = new_sid ? { "session_id" => new_sid } : {}
71
+ req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
68
72
  new_sid
69
73
  end
70
74
 
71
- def load_session(env)
75
+ def load_session(req)
72
76
  stale_session_check! do
73
- data = unpacked_cookie_data(env)
77
+ data = unpacked_cookie_data(req)
74
78
  data = persistent_session_id!(data)
75
- [data["session_id"], data]
79
+ [Rack::Session::SessionId.new(data["session_id"]), data]
76
80
  end
77
81
  end
78
82
 
79
83
  private
80
84
 
81
- def extract_session_id(env)
82
- stale_session_check! do
83
- unpacked_cookie_data(env)["session_id"]
85
+ def extract_session_id(req)
86
+ stale_session_check! do
87
+ sid = unpacked_cookie_data(req)["session_id"]
88
+ sid && Rack::Session::SessionId.new(sid)
89
+ end
84
90
  end
85
- end
86
91
 
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!
92
+ def unpacked_cookie_data(req)
93
+ req.fetch_header("action_dispatch.request.unsigned_session_cookie") do |k|
94
+ v = stale_session_check! do
95
+ if data = get_cookie(req)
96
+ data.stringify_keys!
97
+ end
98
+ data || {}
92
99
  end
93
- data || {}
100
+ req.set_header k, v
94
101
  end
95
102
  end
96
- end
97
103
 
98
- def persistent_session_id!(data, sid=nil)
99
- data ||= {}
100
- data["session_id"] ||= sid || generate_sid
101
- data
102
- end
104
+ def persistent_session_id!(data, sid = nil)
105
+ data ||= {}
106
+ data["session_id"] ||= sid || generate_sid.public_id
107
+ data
108
+ end
103
109
 
104
- def set_session(env, sid, session_data, options)
105
- session_data["session_id"] = sid
106
- session_data
107
- end
110
+ def write_session(req, sid, session_data, options)
111
+ session_data["session_id"] = sid.public_id
112
+ SessionId.new(sid, session_data)
113
+ end
108
114
 
109
- def set_cookie(env, session_id, cookie)
110
- cookie_jar(env)[@key] = cookie
111
- end
115
+ def set_cookie(request, session_id, cookie)
116
+ cookie_jar(request)[@key] = cookie
117
+ end
112
118
 
113
- def get_cookie(env)
114
- cookie_jar(env)[@key]
115
- end
119
+ def get_cookie(req)
120
+ cookie_jar(req)[@key]
121
+ end
116
122
 
117
- def cookie_jar(env)
118
- request = ActionDispatch::Request.new(env)
119
- request.cookie_jar.signed_or_encrypted
120
- end
123
+ def cookie_jar(request)
124
+ request.cookie_jar.signed_or_encrypted
125
+ end
121
126
  end
122
127
  end
123
128
  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,34 @@ 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
40
43
 
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
44
+ def render_exception(request, exception)
45
+ backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
46
+ wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
47
+ status = wrapper.status_code
48
+ request.set_header "action_dispatch.exception", wrapper.exception
49
+ request.set_header "action_dispatch.original_path", request.path_info
50
+ request.path_info = "/#{status}"
51
+ response = @exceptions_app.call(request.env)
52
+ response[1]["X-Cascade"] == "pass" ? pass_response(status) : response
53
+ rescue Exception => failsafe_error
54
+ $stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
55
+ FAILSAFE_RESPONSE
56
+ end
53
57
 
54
- def pass_response(status)
55
- [status, {"Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0"}, []]
56
- end
58
+ def pass_response(status)
59
+ [status, { "Content-Type" => "text/html; charset=#{Response.default_charset}", "Content-Length" => "0" }, []]
60
+ end
57
61
  end
58
62
  end