Skip to content

Commit

Permalink
Use URI::RFC2396_PARSER instead of URI::DEFAULT_PARSER
Browse files Browse the repository at this point in the history
Ruby 3.4 changes `URI::DEFAULT_PARSER` to `URI::RFC3986_Parser`
and deprecates `URI::RFC3986_PARSER.make_regexp`,`URI::RFC3986_PARSER.escape`, `URI::RFC3986_PARSER.unescape` and `URI::RFC3986_PARSER.extract`.

uri v0.12.2 for Ruby 3.2/3.1 and v0.13.1 for Ruby 3.3 adds `URI::RFC2396_PARSER`.
As of right now there is no way to use uri v0.12.2 for Ruby 3.2/3.1 and v0.13.1 for Ruby 3.3,
This commit uses v0.13.1 or higher version for all supported Ruby versions by Rails main branch.

It also reverts rails#52682 because the original issue has been resolved.

Refer to following URL for the backgrond of this change:
- URI::Generic should use URI::RFC3986_PARSER instead of URI::DEFAULT_PARSER
https://bugs.ruby-lang.org/issues/19266

- Use RFC3986_Parser by default
ruby/uri#107

- Warn compatibility methods in RFC3986_PARSER
ruby/uri#114

- Also warn URI::RFC3986_PARSER.extract
ruby/uri#121

- Define RFC2396_PARSER for Ruby 3.3
ruby/uri#119

- Define RFC2396_PARSER for Ruby 3.2 and 3.1
ruby/uri#120
  • Loading branch information
yahonda authored and byroot committed Oct 3, 2024
1 parent 89ce9f6 commit 32ff9d7
Show file tree
Hide file tree
Showing 9 changed files with 12 additions and 12 deletions.
2 changes: 1 addition & 1 deletion actionpack/lib/action_dispatch/routing/inspector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def normalize_filter(filter)
{ controller: /#{filter[:controller].underscore.sub(/_?controller\z/, "")}/ }
elsif filter[:grep]
grep_pattern = Regexp.new(filter[:grep])
path = URI::DEFAULT_PARSER.escape(filter[:grep])
path = URI::RFC2396_PARSER.escape(filter[:grep])
normalized_path = ("/" + path).squeeze("/")

{
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_dispatch/routing/mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2025,7 +2025,7 @@ def add_route(action, controller, options, _path, to, via, formatted, anchor, op
name_for_action(options.delete(:as), action)
end

path = Mapping.normalize_path URI::DEFAULT_PARSER.escape(path), formatted
path = Mapping.normalize_path URI::RFC2396_PARSER.escape(path), formatted
ast = Journey::Parser.parse path

mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_dispatch/routing/route_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ def recognize_path_with_request(req, path, extras, raise_on_missing: true)
params.each do |key, value|
if value.is_a?(String)
value = value.dup.force_encoding(Encoding::BINARY)
params[key] = URI::DEFAULT_PARSER.unescape(value)
params[key] = URI::RFC2396_PARSER.unescape(value)
end
end
req.path_parameters = params
Expand Down
2 changes: 1 addition & 1 deletion actionpack/test/controller/parameter_encoding_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class ParameterEncodingTest < ActionController::TestCase
end

test "does not raise an error when passed a param declared as ASCII-8BIT that contains invalid bytes" do
get :test_skip_parameter_encoding, params: { "bar" => URI::DEFAULT_PARSER.escape("bar\xE2baz".b) }
get :test_skip_parameter_encoding, params: { "bar" => URI::RFC2396_PARSER.escape("bar\xE2baz".b) }

assert_response :success
assert_equal "ASCII-8BIT", @response.body
Expand Down
4 changes: 2 additions & 2 deletions actionpack/test/controller/routing_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2179,11 +2179,11 @@ def test_extras
end

def test_unicode_path
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::DEFAULT_PARSER.escape("こんにちは/世界"), method: :get))
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::RFC2396_PARSER.escape("こんにちは/世界"), method: :get))
end

def test_downcased_unicode_path
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::DEFAULT_PARSER.escape("こんにちは/世界").downcase, method: :get))
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::RFC2396_PARSER.escape("こんにちは/世界").downcase, method: :get))
end

private
Expand Down
4 changes: 2 additions & 2 deletions actionview/lib/action_view/helpers/url_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -556,14 +556,14 @@ def current_page?(options = nil, check_parameters: false, **options_as_kwargs)

options ||= options_as_kwargs
check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
url_string = URI::DEFAULT_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)
url_string = URI::RFC2396_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)

# We ignore any extra parameters in the request_uri if the
# submitted URL doesn't have any either. This lets the function
# work with things like ?order=asc
# the behavior can be disabled with check_parameters: true
request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
request_uri = URI::DEFAULT_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)
request_uri = URI::RFC2396_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)

if %r{^\w+://}.match?(url_string)
request_uri = +"#{request.protocol}#{request.host_with_port}#{request_uri}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def to_hash
attr_reader :uri

def uri_parser
@uri_parser ||= URI::Parser.new
@uri_parser ||= URI::RFC2396_Parser.new
end

# Converts the query parameters of the URI into a hash.
Expand Down
4 changes: 2 additions & 2 deletions railties/lib/rails/info_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def properties

def routes
if query = params[:query]
query = URI::DEFAULT_PARSER.escape query
query = URI::RFC2396_PARSER.escape query

render json: {
exact: matching_routes(query: query, exact_match: true),
Expand Down Expand Up @@ -53,7 +53,7 @@ def matching_routes(query:, exact_match:)
match ||= (query === route_wrapper.verb)

unless match
controller_action = URI::DEFAULT_PARSER.escape(route_wrapper.reqs)
controller_action = URI::RFC2396_PARSER.escape(route_wrapper.reqs)
match = exact_match ? (query === controller_action) : controller_action.include?(query)
end

Expand Down
2 changes: 1 addition & 1 deletion railties/test/application/assets_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ class User < ActiveRecord::Base; raise 'should not be reached'; end
# Load app env
app "development"

get "/assets/#{URI::DEFAULT_PARSER.escape(asset_path)}"
get "/assets/#{URI::RFC2396_PARSER.escape(asset_path)}"
assert_match "not an image really", last_response.body
assert_file_exists("#{app_path}/public/assets/#{asset_path}")
end
Expand Down

0 comments on commit 32ff9d7

Please sign in to comment.