Accept headers allow parameters to be passed. They can contain quotes
that need to be handled differently. These quoted strings can contain
commas, which are not considered as delimiters of accept headers.
Additionally, all parameters before the q-parameter should be used to
lookup the media-type as well. If no media-type with the parameters is
found, a fallback is introduced to the media-type without any parameters
to keep the same functionality as before.
Fix#48052
The url_for helper now supports a new option called `bind_params`.
This is very useful in situations where you only want to add a required
param that is part of the route's URL but for other route not append an
extraneous query param.
Given the following router...
```ruby
Rails.application.routes.draw do
scope ":account_id" do
get 'dashboard' => 'pages#dashboard', as: :dashboard
get 'search/:term' => 'search#search', as: :search
end
delete 'signout' => 'sessions#destroy', as: :signout
end
```
And given the following `ApplicationController`
```ruby
class ApplicationController < ActionController::Base
def default_url_options
{ bind_params: { account_id: "foo" } }
end
end
```
The standard URLHelpers will now behave as follows:
```ruby
dashboard_path # => /foo/dashboard
dashboard_path(account_id: "bar") # => /bar/dashboard
signout_path # => /signout
signout_path(account_id: "bar") # => /signout?account_id=bar
search_path("quin") # => /foo/search/quin
```
Background
----------
During integration tests, it is desirable for the application to respond
as closely as possible to the way it would in production. This improves
confidence that the application behavior acts as it should.
In Rails tests, one major mismatch between the test and production
environments is that exceptions raised during an HTTP request (e.g.
`ActiveRecord::RecordNotFound`) are re-raised within the test rather
than rescued and then converted to a 404 response.
Setting `config.action_dispatch.show_exceptions` to `true` will make the
test environment act like production, however, when an unexpected
internal server error occurs, the test will be left with a opaque 500
response rather than presenting a useful stack trace. This makes
debugging more difficult.
This leaves the developer with choosing between higher quality
integration tests or an improved debugging experience on a failure.
I propose that we can achieve both.
Solution
--------
Change the configuration option `config.action_dispatch.show_exceptions`
from a boolean to one of 3 values: `:all`, `:rescuable`, `:none`. The
values `:all` and `:none` behaves the same as the previous `true` and
`false` respectively. What was previously `true` (now `:all`) continues
to be the default for non-test environments.
The new `:rescuable` value is the new default for the test environment.
It will show exceptions in the response only for rescuable exceptions as
defined by `ActionDispatch::ExceptionWrapper.rescue_responses`. In the
event of an unexpected internal server error, the exception that caused
the error will still be raised within the test so as to provide a useful
stack trace and a good debugging experience.
This commit adds support for `:message_pack` and `:message_pack_allow_marshal`
as serializers for `config.action_dispatch.cookies_serializer`, just
like `config.active_support.message_serializer`.
The `:message_pack` serializer can fall back to deserializing with
`AS::JSON`, and the `:message_pack_allow_marshal` serializer can fall
back to deserializing with `AS::JSON` or `Marshal`. Additionally, the
`:marshal`, `:json`, and `:hybrid` / `:json_allow_marshal` serializers
can now fall back to deserializing with `AS::MessagePack`. These
behaviors make it easier to migrate between cookies serializers.
Rails has incorrectly been adding leading dots to cookie domain values
when the `domain: :all` option is present.
This leading dot was required in cookies based on [RFC 2965][rfc2965]
(October 2000), but [RFC 6265][rfc6265] (April 2011) changed that
behaviour, making a leading dot strictly incorrect. Todays browsers aim
to confirm to RFC6265 with repect to cookies.
The new behaviour is that *any* cookie with an explicitly passed domain
is sent to all matching subdomains[[ref][mdn]]. For a server to indicate
that only the exact origin server should receive the cookie, it should
instead pass *no* domain attribute.
Despite the change in behaviour, browser devtools often display a cookie
domain with a leading dot to indicate that it is valid for subdomains -
this prefixed domain is *not* necessarily the raw value that was passed
in the Set-Cookie header. This explains why it's a common belief among
developers that the leading dot is required.
RFC6265 standard gives UAs an algorithm to handle old-style cookie
domain parameters (they can drop a leading dot if present), so it's
unlikely that this error would ever have had any effect on web browsers.
However, cookies generated this way can't be processed by Ruby's own
CGI::Cookie class:
> CGI::Cookie.new "domain" => ".foo.bar", "name" => "foo"
ArgumentError: invalid domain: ".foo.bar"
Newer versions of the Ruby CGI library accomodate the same fallback
behaviour (dropping the extra dot) but this isn't a justification for it
being the right way to set a cookie.
[mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#domain_attribute
[rfc2965]: https://www.rfc-editor.org/rfc/rfc2965#section-3.2
[rfc6265]: https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1
Expands the search field on the rails/info/routes page to also search:
* Route name (with or without a _path and _url extension)
* HTTP Verb (eg. GET/POST/PUT etc.)
* Controller#Action
because it's not obvious that the search field is currently only
restricted to the route paths.
This error used to be a wrapper for a LoadError raised when
require_dependency was used to load helpers for controllers.
Since Zeitwerk does not use require_dependency, the only usage of the
error was removed in 5b28a0e972da31da570ed24be505ef7958ab4b5e.
Prior to this commit, the only out-of-the-box parsing that
`ActionDispatch::Testing::TestResponse#parsed_body` supported was for
`application/json` requests. This meant that `response.body ==
response.parsed_body` for HTML requests.
```ruby
get "/posts"
response.content_type # => "text/html; charset=utf-8"
response.parsed_body.class # => Nokogiri::HTML5::Document
response.parsed_body.to_html # => "<!DOCTYPE html>\n<html>\n..."
```
Using `parsed_body` for JSON requests supports `Hash#fetch`, `Hash#dig`,
and Ruby 3.2 destructuring assignment and pattern matching.
The introduction of [Nokogiri support for pattern
matching][nokogiri-pattern-matching] poses an opportunity to make assertions
about the structure of the HTML response.
On top of that, there is ongoing work to [introduce pattern matching
support in MiniTest][minitest-pattern-matching].
[nokogiri-pattern-matching]: https://github.com/sparklemotion/nokogiri/pull/2523
[minitest-pattern-matching]: https://github.com/minitest/minitest/pull/936
In the GitHub RoR monolith, we output the route URI pattern
in an HTML meta tag in our application layout for analysis
purposes. However, our current implementation is quite manual.
This change adds an attribute to requests with the URI pattern
of the matched route.
Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
Co-authored-by: Kate Higa <khiga8@github.com>
* Allow use of SSL-terminating reserve proxy that doesn't set headers
NGINX and other SSL-terminating reverse proxies can use HTTP headers to include forwarding information. If your stack includes SSL-termination through a network load balancer, that won't happen. You can use config.assume_ssl to address that.
* I hate these warts
* Document the new setting
* Add autoload for AssumeSSL
* Add CHANGELOG notice
In #43487 we missed adding a changelog so that's been added here. In
addition, since this isn't a new framework default unless you are
creating a new application (and only in dev and test environments by
default) it can be easy to miss this new option. I've updated the
message to mention the option following DHH's suggestion on the original
PR.
When a host is not specified for an `ActionController::Renderer`'s env,
the host and related options will now be derived from the routes'
`default_url_options` and `ActionDispatch::Http::URL.secure_protocol`.
For example, with:
```ruby
Rails.application.default_url_options = { host: "rubyonrails.org" }
Rails.application.config.force_ssl = true
```
Before:
```ruby
ApplicationController.renderer.render inline: "<%= blog_url %>"
# => "http://example.org/blog"
```
After:
```ruby
ApplicationController.renderer.render inline: "<%= blog_url %>"
# => "https://rubyonrails.org/blog"
```
As a consequence, Action Text attachment URLs rendered in a background
job (a la Turbo Streams) will now use `Rails.application.default_url_options`.
Fixes#41795.
Fixeshotwired/turbo-rails#54.
Fixeshotwired/turbo-rails#155.
ref: https://github.com/rails/rails/pull/46279
That PR missed the case where if you set `config.active_record.query_log_tags = [:namespaced_controller]`, it would log the controller twice:
```
/*namespaced_controller:Foo::BarController,controller:bar*
```
So this PR just fixes that bug, and tweaks the changelog entry rather than adding another one for the same bug.
My app was raising a `CookieOverflow` exception but it was difficult to pinpoint the cause, since error trackers and logging system generally filter out cookies.
This Pull Request has been created because I want the exception to provide additional information:
- The name of the cookie that overflowed
- The magnitude of how much it overflowed by
I am assuming that only the cookie value is sensitive, and not its name or size.
Fixes https://github.com/rails/rails/issues/46103
An issue exists if you set `config.active_record.query_log_tags` to an array that includes `:controller`, `:action`, or `:job`; the relevant item will get duplicated in the log line. This occured because the relevant railties would add the item to `config.active_record.query_log_tags` again during setup. This PR fixes that by only adding those items to the config if they aren't already set.
The issue proposed more documentation to work around this, but I think it's a bug and should be fixed directly.
Previously, the method always asserts the status is `:redirect` which
allows for any kind of 3XX response. However, sometimes it is worthwhile
to precise the status code of the redirect. For example, a Rails
application may want to verify the redirect is a 301 (Moved Permanently)
and not the default 302 (Found). The new method argument makes this
convenient to do in one assertion.
Without this change if action_dispatch.cookies_serializer is set to
json and the app tries to read a marshal-serialized cookie, it will
raise a JSON::ParserError which won't clear the cookie and force app
users to manually clear the cookie in their browser.
(See #45127 for original bug discussion)
Since 7ccaa125ba it's not been possible to not include `SameSite` on your cookies. `SameSite` is recommended, but it's not a required field, and you should be able to opt out of it.
This PR introduces that ability: you can opt out of `SameSite` by passing `same_site: false`.
```ruby
cookies[:foo] = { value: "bar", same_site: false }
```
Previously, this incorrectly set the `SameSite` attribute to the value of the `cookies_same_site_protection` setting. https://github.com/rails/rails/pull/44934 added docs saying that you could pass `nil` as a value, but that also would fall back to the default (`:lax`).