actionpack 8.0.2.1 → 8.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cb8e992334f0e3f93612b4537cc5ba4ce6bd5c3dc08e8af9d80ab52c83da4ea
4
- data.tar.gz: 65cb880c5201bbd397b7da6e9c74e9979f4d96c4767d737788ed8cfb045b0592
3
+ metadata.gz: b131da258151267320d978699cdc9ed60f96060bbeeb5bfa85f8da0ab648497f
4
+ data.tar.gz: 2300ba0391c2e63f5e0ab71060bec7ef3e149d32064e5eccfd1a1f46ecad2820
5
5
  SHA512:
6
- metadata.gz: 9f6fea1838782b52b118384a0a3f9f1dd7a97503b2dcfcbd629e18126b9f4bfdf5e9bc506936b345d178f29ee92714ec6e462efa49dfe5c2768c75b38e9c9e00
7
- data.tar.gz: 9e707325f4080e40f36ae4815a247f6ece5ab56e392f6b9c71d1c5bed34b66e63be49f75a747904388fe6ecf47a4964447a4ac01db60fd6286a80bce773673aa
6
+ metadata.gz: 13ee7198d843341f8b97aa564b70385fd26ee5e3bdd2560e56cc20a16591d8502daa4befec55a81bc4783e5451648acf35dd67de6ca62cf0b41f5ae37cec9557
7
+ data.tar.gz: 17972b2a557984ad9a96f3947135fe29dd6aae6dfd0a019204be60e0d82056ed390333bad574ae9ec8d762b24574f4aac8103e04d647fca3a75736763ecae9f6
data/CHANGELOG.md CHANGED
@@ -1,12 +1,47 @@
1
- ## Rails 8.0.2.1 (August 13, 2025) ##
1
+ ## Rails 8.0.3 (September 22, 2025) ##
2
2
 
3
- * No changes.
3
+ * URL helpers for engines mounted at the application root handle `SCRIPT_NAME` correctly.
4
4
 
5
+ Fixed an issue where `SCRIPT_NAME` is not applied to paths generated for routes in an engine
6
+ mounted at "/".
5
7
 
6
- ## Rails 8.0.2 (March 12, 2025) ##
8
+ *Mike Dalessio*
7
9
 
8
- * No changes.
10
+ * Fix `Rails.application.reload_routes!` from clearing almost all routes.
11
+
12
+ When calling `Rails.application.reload_routes!` inside a middleware of
13
+ a Rake task, it was possible under certain conditions that all routes would be cleared.
14
+ If ran inside a middleware, this would result in getting a 404 on most page you visit.
15
+ This issue was only happening in development.
16
+
17
+ *Edouard Chin*
18
+
19
+ * Address `rack 3.2` deprecations warnings.
20
+
21
+ ```
22
+ warning: Status code :unprocessable_entity is deprecated and will be removed in a future version of Rack.
23
+ Please use :unprocessable_content instead.
24
+ ```
25
+
26
+ Rails API will transparently convert one into the other for the foreseeable future.
9
27
 
28
+ *Earlopain*, *Jean Boussier*
29
+
30
+ * Support hash-source in Content Security Policy.
31
+
32
+ *madogiwa*
33
+
34
+ * Always return empty body for HEAD requests in `PublicExceptions` and
35
+ `DebugExceptions`.
36
+
37
+ This is required by `Rack::Lint` (per RFC9110).
38
+
39
+ *Hartley McGuire*
40
+
41
+
42
+ ## Rails 8.0.2.1 (August 13, 2025) ##
43
+
44
+ * No changes.
10
45
 
11
46
  ## Rails 8.0.2 (March 12, 2025) ##
12
47
 
data/README.rdoc CHANGED
@@ -52,6 +52,6 @@ Bug reports for the Ruby on \Rails project can be filed here:
52
52
 
53
53
  * https://github.com/rails/rails/issues
54
54
 
55
- Feature requests should be discussed on the rails-core mailing list here:
55
+ Feature requests should be discussed on the rubyonrails-core forum here:
56
56
 
57
57
  * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -86,14 +86,10 @@ module AbstractController
86
86
  controller.public_instance_methods(true) - methods
87
87
  end
88
88
 
89
- # A list of method names that should be considered actions. This includes all
89
+ # A `Set` of method names that should be considered actions. This includes all
90
90
  # public instance methods on a controller, less any internal methods (see
91
91
  # internal_methods), adding back in any methods that are internal, but still
92
92
  # exist on the class itself.
93
- #
94
- # #### Returns
95
- # * `Set` - A set of all methods that should be considered actions.
96
- #
97
93
  def action_methods
98
94
  @action_methods ||= begin
99
95
  # All public instance methods of this class, including ancestors except for
@@ -121,9 +117,6 @@ module AbstractController
121
117
  #
122
118
  # MyApp::MyPostsController.controller_path # => "my_app/my_posts"
123
119
  #
124
- # #### Returns
125
- # * `String`
126
- #
127
120
  def controller_path
128
121
  @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous?
129
122
  end
@@ -147,10 +140,6 @@ module AbstractController
147
140
  # The actual method that is called is determined by calling #method_for_action.
148
141
  # If no method can handle the action, then an AbstractController::ActionNotFound
149
142
  # error is raised.
150
- #
151
- # #### Returns
152
- # * `self`
153
- #
154
143
  def process(action, ...)
155
144
  @_action_name = action.to_s
156
145
 
@@ -27,7 +27,7 @@ module AbstractController
27
27
  def method_missing(symbol, ...)
28
28
  unless mime_constant = Mime[symbol]
29
29
  raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
30
- "https://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
30
+ "https://guides.rubyonrails.org/action_controller_advanced_topics.html#restful-downloads. " \
31
31
  "If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
32
32
  "be sure to nest your variant response within a format response: " \
33
33
  "format.html { |html| html.tablet { ... } }"
@@ -171,12 +171,6 @@ module ActionController
171
171
  @ignore_disconnect = false
172
172
  end
173
173
 
174
- # ActionDispatch::Response delegates #to_ary to the internal
175
- # ActionDispatch::Response::Buffer, defining #to_ary is an indicator that the
176
- # response body can be buffered and/or cached by Rack middlewares, this is not
177
- # the case for Live responses so we undefine it for this Buffer subclass.
178
- undef_method :to_ary
179
-
180
174
  def write(string)
181
175
  unless @response.committed?
182
176
  @response.headers["Cache-Control"] ||= "no-cache"
@@ -212,9 +212,9 @@ module ActionController
212
212
 
213
213
  def _extract_redirect_to_status(options, response_options)
214
214
  if options.is_a?(Hash) && options.key?(:status)
215
- Rack::Utils.status_code(options.delete(:status))
215
+ ActionDispatch::Response.rack_status_code(options.delete(:status))
216
216
  elsif response_options.key?(:status)
217
- Rack::Utils.status_code(response_options[:status])
217
+ ActionDispatch::Response.rack_status_code(response_options[:status])
218
218
  else
219
219
  302
220
220
  end
@@ -232,7 +232,7 @@ module ActionController
232
232
  end
233
233
 
234
234
  if options[:status]
235
- options[:status] = Rack::Utils.status_code(options[:status])
235
+ options[:status] = ActionDispatch::Response.rack_status_code(options[:status])
236
236
  end
237
237
 
238
238
  super
@@ -96,7 +96,6 @@ module ActionController
96
96
  # * `:script_name` - The portion of the incoming request's URL path that
97
97
  # corresponds to the application. Converts to Rack's `SCRIPT_NAME`.
98
98
  # * `:input` - The input stream. Converts to Rack's `rack.input`.
99
- #
100
99
  # * `defaults` - Default values for the Rack env. Entries are specified in the
101
100
  # same format as `env`. `env` will be merged on top of these values.
102
101
  # `defaults` will be retained when calling #new on a renderer instance.
@@ -30,5 +30,11 @@ module ActionDispatch
30
30
  SERVER_TIMING = "server-timing"
31
31
  STRICT_TRANSPORT_SECURITY = "strict-transport-security"
32
32
  end
33
+
34
+ if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3.1")
35
+ UNPROCESSABLE_CONTENT = :unprocessable_entity
36
+ else
37
+ UNPROCESSABLE_CONTENT = :unprocessable_content
38
+ end
33
39
  end
34
40
  end
@@ -171,6 +171,8 @@ module ActionDispatch # :nodoc:
171
171
  worker_src: "worker-src"
172
172
  }.freeze
173
173
 
174
+ HASH_SOURCE_ALGORITHM_PREFIXES = ["sha256-", "sha384-", "sha512-"].freeze
175
+
174
176
  DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
175
177
 
176
178
  private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES
@@ -305,7 +307,13 @@ module ActionDispatch # :nodoc:
305
307
  case source
306
308
  when Symbol
307
309
  apply_mapping(source)
308
- when String, Proc
310
+ when String
311
+ if hash_source?(source)
312
+ "'#{source}'"
313
+ else
314
+ source
315
+ end
316
+ when Proc
309
317
  source
310
318
  else
311
319
  raise ArgumentError, "Invalid content security policy source: #{source.inspect}"
@@ -374,5 +382,9 @@ module ActionDispatch # :nodoc:
374
382
  def nonce_directive?(directive, nonce_directives)
375
383
  nonce_directives.include?(directive)
376
384
  end
385
+
386
+ def hash_source?(source)
387
+ source.start_with?(*HASH_SOURCE_ALGORITHM_PREFIXES)
388
+ end
377
389
  end
378
390
  end
@@ -56,9 +56,14 @@ module ActionDispatch
56
56
 
57
57
  # Returns the MIME type for the format used in the request.
58
58
  #
59
- # GET /posts/5.xml | request.format => Mime[:xml]
60
- # GET /posts/5.xhtml | request.format => Mime[:html]
61
- # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
59
+ # # GET /posts/5.xml
60
+ # request.format # => Mime[:xml]
61
+ #
62
+ # # GET /posts/5.xhtml
63
+ # request.format # => Mime[:html]
64
+ #
65
+ # # GET /posts/5
66
+ # request.format # => Mime[:html] or Mime[:js], or request.accepts.first
62
67
  #
63
68
  def format(_view_path = nil)
64
69
  formats.first || Mime::NullType.instance
@@ -46,6 +46,20 @@ module ActionDispatch # :nodoc:
46
46
  Headers = ::Rack::Utils::HeaderHash
47
47
  end
48
48
 
49
+ class << self
50
+ if ActionDispatch::Constants::UNPROCESSABLE_CONTENT == :unprocessable_content
51
+ def rack_status_code(status) # :nodoc:
52
+ status = :unprocessable_content if status == :unprocessable_entity
53
+ Rack::Utils.status_code(status)
54
+ end
55
+ else
56
+ def rack_status_code(status) # :nodoc:
57
+ status = :unprocessable_entity if status == :unprocessable_content
58
+ Rack::Utils.status_code(status)
59
+ end
60
+ end
61
+ end
62
+
49
63
  # To be deprecated:
50
64
  Header = Headers
51
65
 
@@ -105,10 +119,22 @@ module ActionDispatch # :nodoc:
105
119
  @str_body = nil
106
120
  end
107
121
 
122
+ BODY_METHODS = { to_ary: true }
123
+
124
+ def respond_to?(method, include_private = false)
125
+ if BODY_METHODS.key?(method)
126
+ @buf.respond_to?(method)
127
+ else
128
+ super
129
+ end
130
+ end
131
+
108
132
  def to_ary
109
- @buf.respond_to?(:to_ary) ?
110
- @buf.to_ary :
111
- @buf.each
133
+ if @str_body
134
+ [body]
135
+ else
136
+ @buf = @buf.to_ary
137
+ end
112
138
  end
113
139
 
114
140
  def body
@@ -245,7 +271,7 @@ module ActionDispatch # :nodoc:
245
271
 
246
272
  # Sets the HTTP status code.
247
273
  def status=(status)
248
- @status = Rack::Utils.status_code(status)
274
+ @status = Response.rack_status_code(status)
249
275
  end
250
276
 
251
277
  # Sets the HTTP response's content MIME type. For example, in the controller you
@@ -328,7 +354,13 @@ module ActionDispatch # :nodoc:
328
354
  # Returns the content of the response as a string. This contains the contents of
329
355
  # any calls to `render`.
330
356
  def body
331
- @stream.body
357
+ if @stream.respond_to?(:to_ary)
358
+ @stream.to_ary.join
359
+ elsif @stream.respond_to?(:body)
360
+ @stream.body
361
+ else
362
+ @stream
363
+ end
332
364
  end
333
365
 
334
366
  def write(string)
@@ -337,11 +369,16 @@ module ActionDispatch # :nodoc:
337
369
 
338
370
  # Allows you to manually set or override the response body.
339
371
  def body=(body)
340
- if body.respond_to?(:to_path)
341
- @stream = body
342
- else
343
- synchronize do
344
- @stream = build_buffer self, munge_body_object(body)
372
+ # Prevent ActionController::Metal::Live::Response from committing the response prematurely.
373
+ synchronize do
374
+ if body.respond_to?(:to_str)
375
+ @stream = build_buffer(self, [body])
376
+ elsif body.respond_to?(:to_path)
377
+ @stream = body
378
+ elsif body.respond_to?(:to_ary)
379
+ @stream = build_buffer(self, body)
380
+ else
381
+ @stream = body
345
382
  end
346
383
  end
347
384
  end
@@ -482,10 +519,6 @@ module ActionDispatch # :nodoc:
482
519
  Buffer.new response, body
483
520
  end
484
521
 
485
- def munge_body_object(body)
486
- body.respond_to?(:each) ? body : [body]
487
- end
488
-
489
522
  def assign_default_content_type_and_charset!
490
523
  return if media_type
491
524
 
@@ -499,6 +532,8 @@ module ActionDispatch # :nodoc:
499
532
  @response = response
500
533
  end
501
534
 
535
+ attr :response
536
+
502
537
  def close
503
538
  # Rack "close" maps to Response#abort, and **not** Response#close (which is used
504
539
  # when the controller's finished writing)
@@ -272,7 +272,7 @@ module ActionDispatch
272
272
  end
273
273
  end
274
274
 
275
- # Returns whether this request is using the standard port
275
+ # Returns whether this request is using the standard port.
276
276
  #
277
277
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
278
278
  # req.standard_port? # => true
@@ -307,7 +307,7 @@ module ActionDispatch
307
307
  standard_port? ? "" : ":#{port}"
308
308
  end
309
309
 
310
- # Returns the requested port, such as 8080, based on SERVER_PORT
310
+ # Returns the requested port, such as 8080, based on SERVER_PORT.
311
311
  #
312
312
  # req = ActionDispatch::Request.new 'SERVER_PORT' => '80'
313
313
  # req.server_port # => 80
@@ -107,10 +107,10 @@ module ActionDispatch
107
107
  end
108
108
 
109
109
  {
110
- regexp_states: simple_regexp,
111
- string_states: @string_states,
112
- stdparam_states: @stdparam_states,
113
- accepting: @accepting
110
+ regexp_states: simple_regexp.stringify_keys,
111
+ string_states: @string_states.stringify_keys,
112
+ stdparam_states: @stdparam_states.stringify_keys,
113
+ accepting: @accepting.stringify_keys
114
114
  }
115
115
  end
116
116
 
@@ -65,7 +65,9 @@ module ActionDispatch
65
65
  content_type = Mime[:text]
66
66
  end
67
67
 
68
- if api_request?(content_type)
68
+ if request.head?
69
+ render(wrapper.status_code, "", content_type)
70
+ elsif api_request?(content_type)
69
71
  render_for_api_request(content_type, wrapper)
70
72
  else
71
73
  render_for_browser_request(request, wrapper)
@@ -18,8 +18,8 @@ module ActionDispatch
18
18
  "ActionController::UnknownFormat" => :not_acceptable,
19
19
  "ActionDispatch::Http::MimeNegotiation::InvalidType" => :not_acceptable,
20
20
  "ActionController::MissingExactTemplate" => :not_acceptable,
21
- "ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
22
- "ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
21
+ "ActionController::InvalidAuthenticityToken" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT,
22
+ "ActionController::InvalidCrossOriginRequest" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT,
23
23
  "ActionDispatch::Http::Parameters::ParseError" => :bad_request,
24
24
  "ActionController::BadRequest" => :bad_request,
25
25
  "ActionController::ParameterMissing" => :bad_request,
@@ -173,7 +173,7 @@ module ActionDispatch
173
173
  end
174
174
 
175
175
  def self.status_code_for_exception(class_name)
176
- Rack::Utils.status_code(@@rescue_responses[class_name])
176
+ ActionDispatch::Response.rack_status_code(@@rescue_responses[class_name])
177
177
  end
178
178
 
179
179
  def show?(request)
@@ -32,7 +32,11 @@ module ActionDispatch
32
32
  end
33
33
  body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
34
34
 
35
- render(status, content_type, body)
35
+ if env["action_dispatch.original_request_method"] == "HEAD"
36
+ render_format(status, content_type, "")
37
+ else
38
+ render(status, content_type, body)
39
+ end
36
40
  end
37
41
 
38
42
  private
@@ -29,7 +29,7 @@ module ActionDispatch
29
29
  def from_requirements(requirements)
30
30
  routes.find { |route| route.requirements == requirements }
31
31
  end
32
- # :stopdoc:
32
+ # :enddoc:
33
33
 
34
34
  # Since the router holds references to many parts of the system like engines,
35
35
  # controllers and the application itself, inspecting the route set can actually
@@ -953,6 +953,5 @@ module ActionDispatch
953
953
  end
954
954
  end
955
955
  end
956
- # :startdoc:
957
956
  end
958
957
  end
@@ -54,6 +54,7 @@ module ActionDispatch
54
54
  # dependent part.
55
55
  def merge_script_names(previous_script_name, new_script_name)
56
56
  return new_script_name unless previous_script_name
57
+ new_script_name = new_script_name.chomp("/")
57
58
 
58
59
  resolved_parts = new_script_name.count("/")
59
60
  previous_parts = previous_script_name.count("/")
@@ -38,7 +38,7 @@ module ActionDispatch
38
38
 
39
39
  private
40
40
  def code_from_name(name)
41
- GENERIC_RESPONSE_CODES[name] || Rack::Utils.status_code(name)
41
+ GENERIC_RESPONSE_CODES[name] || ActionDispatch::Response.rack_status_code(name)
42
42
  end
43
43
 
44
44
  def name_from_code(code)
@@ -604,9 +604,8 @@ module ActionDispatch
604
604
  # end
605
605
  # end
606
606
  #
607
- # See the [request helpers documentation]
608
- # (rdoc-ref:ActionDispatch::Integration::RequestHelpers) for help
609
- # on how to use `get`, etc.
607
+ # See the [request helpers documentation](rdoc-ref:ActionDispatch::Integration::RequestHelpers)
608
+ # for help on how to use `get`, etc.
610
609
  #
611
610
  # ### Changing the request encoding
612
611
  #
@@ -11,8 +11,8 @@ module ActionPack
11
11
  module VERSION
12
12
  MAJOR = 8
13
13
  MINOR = 0
14
- TINY = 2
15
- PRE = "1"
14
+ TINY = 3
15
+ PRE = nil
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
18
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.2.1
4
+ version: 8.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 8.0.2.1
18
+ version: 8.0.3
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 8.0.2.1
25
+ version: 8.0.3
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: nokogiri
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -127,28 +127,28 @@ dependencies:
127
127
  requirements:
128
128
  - - '='
129
129
  - !ruby/object:Gem::Version
130
- version: 8.0.2.1
130
+ version: 8.0.3
131
131
  type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - '='
136
136
  - !ruby/object:Gem::Version
137
- version: 8.0.2.1
137
+ version: 8.0.3
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: activemodel
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
- version: 8.0.2.1
144
+ version: 8.0.3
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - '='
150
150
  - !ruby/object:Gem::Version
151
- version: 8.0.2.1
151
+ version: 8.0.3
152
152
  description: Web apps on Rails. Simple, battle-tested conventions for building and
153
153
  testing MVC web applications. Works with any Rack-compatible server.
154
154
  email: david@loudthinking.com
@@ -349,10 +349,10 @@ licenses:
349
349
  - MIT
350
350
  metadata:
351
351
  bug_tracker_uri: https://github.com/rails/rails/issues
352
- changelog_uri: https://github.com/rails/rails/blob/v8.0.2.1/actionpack/CHANGELOG.md
353
- documentation_uri: https://api.rubyonrails.org/v8.0.2.1/
352
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.3/actionpack/CHANGELOG.md
353
+ documentation_uri: https://api.rubyonrails.org/v8.0.3/
354
354
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
355
- source_code_uri: https://github.com/rails/rails/tree/v8.0.2.1/actionpack
355
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.3/actionpack
356
356
  rubygems_mfa_required: 'true'
357
357
  rdoc_options: []
358
358
  require_paths: