From db89644396786767c9402a852c77d6f9139df9db Mon Sep 17 00:00:00 2001 From: Theodor Fiedler Date: Mon, 1 Apr 2024 23:34:42 +0200 Subject: [PATCH 1/3] Translate `:undefined` URI port to `nil` Resolves #13462 When a url string is schema less and the host is followed by a colon without setting the actual port, `:uri_string.parse/1` returns the port to be `:undefined`. As long as the url string is parseable, we should translate `:undefiend` to `nil`, in order to ensure we return a valid URI struct. --- lib/elixir/lib/uri.ex | 3 +++ lib/elixir/test/elixir/uri_test.exs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/elixir/lib/uri.ex b/lib/elixir/lib/uri.ex index 0a1858cf964..2538c8e4644 100644 --- a/lib/elixir/lib/uri.ex +++ b/lib/elixir/lib/uri.ex @@ -666,6 +666,9 @@ defmodule URI do end end + %{port: :undefined} -> + %{uri | port: nil} + %{} -> uri end diff --git a/lib/elixir/test/elixir/uri_test.exs b/lib/elixir/test/elixir/uri_test.exs index e465cb323e3..6ed3bf94da7 100644 --- a/lib/elixir/test/elixir/uri_test.exs +++ b/lib/elixir/test/elixir/uri_test.exs @@ -97,6 +97,20 @@ defmodule URITest do assert URI.new("") == {:ok, %URI{}} end + test "missing port part after host never resolves to :undefined" do + assert URI.new("//https://www.example.com") == + {:ok, + %URI{ + scheme: nil, + userinfo: nil, + host: "https", + port: nil, + path: "//www.example.com", + query: nil, + fragment: nil + }} + end + test "errors on bad URIs" do assert URI.new("/>") == {:error, ">"} assert URI.new(":https") == {:error, ":"} From ed85d094c44ca637e400816fbf83bc98cd2b8af9 Mon Sep 17 00:00:00 2001 From: Theodor Fiedler Date: Tue, 2 Apr 2024 03:56:57 +0200 Subject: [PATCH 2/3] handle undefined port with custom scheme --- lib/elixir/lib/uri.ex | 5 +++- lib/elixir/test/elixir/uri_test.exs | 40 +++++++++++++++++++---------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/elixir/lib/uri.ex b/lib/elixir/lib/uri.ex index 2538c8e4644..3434c1b1355 100644 --- a/lib/elixir/lib/uri.ex +++ b/lib/elixir/lib/uri.ex @@ -656,9 +656,12 @@ defmodule URI do scheme = String.downcase(scheme, :ascii) case map do - %{port: port} when port != :undefined -> + %{port: port} when is_integer(port) -> %{uri | scheme: scheme} + %{port: :undefined} -> + %{uri | scheme: scheme, port: default_port(scheme)} + %{} -> case default_port(scheme) do nil -> %{uri | scheme: scheme} diff --git a/lib/elixir/test/elixir/uri_test.exs b/lib/elixir/test/elixir/uri_test.exs index 6ed3bf94da7..8772ec97d3c 100644 --- a/lib/elixir/test/elixir/uri_test.exs +++ b/lib/elixir/test/elixir/uri_test.exs @@ -97,20 +97,6 @@ defmodule URITest do assert URI.new("") == {:ok, %URI{}} end - test "missing port part after host never resolves to :undefined" do - assert URI.new("//https://www.example.com") == - {:ok, - %URI{ - scheme: nil, - userinfo: nil, - host: "https", - port: nil, - path: "//www.example.com", - query: nil, - fragment: nil - }} - end - test "errors on bad URIs" do assert URI.new("/>") == {:error, ">"} assert URI.new(":https") == {:error, ":"} @@ -291,6 +277,32 @@ defmodule URITest do test "preserves an empty query" do assert URI.new!("http://foo.com/?").query == "" end + + test "without scheme, undefined port after host translates to nil" do + assert URI.new!("//https://www.example.com") == + %URI{ + scheme: nil, + userinfo: nil, + host: "https", + port: nil, + path: "//www.example.com", + query: nil, + fragment: nil + } + end + + test "with scheme, undefined port after host translates to nil" do + assert URI.new!("myscheme://myhost:/path/info") == + %URI{ + scheme: "myscheme", + userinfo: nil, + host: "myhost", + port: nil, + path: "/path/info", + query: nil, + fragment: nil + } + end end test "http://http://http://@http://http://?http://#http://" do From b816d36555cc0c171fee1da67f321abe01593f5a Mon Sep 17 00:00:00 2001 From: Theodor Fiedler Date: Tue, 2 Apr 2024 04:04:20 +0200 Subject: [PATCH 3/3] simplify nested case statement --- lib/elixir/lib/uri.ex | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/elixir/lib/uri.ex b/lib/elixir/lib/uri.ex index 3434c1b1355..b6eeef526ad 100644 --- a/lib/elixir/lib/uri.ex +++ b/lib/elixir/lib/uri.ex @@ -659,14 +659,8 @@ defmodule URI do %{port: port} when is_integer(port) -> %{uri | scheme: scheme} - %{port: :undefined} -> - %{uri | scheme: scheme, port: default_port(scheme)} - %{} -> - case default_port(scheme) do - nil -> %{uri | scheme: scheme} - port -> %{uri | scheme: scheme, port: port} - end + %{uri | scheme: scheme, port: default_port(scheme)} end %{port: :undefined} ->