diff options
author | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2019-12-05 21:49:32 +0100 |
---|---|---|
committer | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2019-12-06 03:55:20 +0100 |
commit | 6f513f3bab8fd27b0b72ba5c94355b219da61805 (patch) | |
tree | 07735de3f69234ee70b3530dbd107edd4c94ca51 | |
parent | 0a33059a10092960219983caafe4aad96eb5a980 (diff) | |
download | elixir-emj/uri-preserve-slashes.tar.gz |
Preserve slashes in URIs without authorityemj/uri-preserve-slashes
Old behavior:
to_string(URI.parse("file:///path")) == "file:/path"
New behavior:
to_string(URI.parse("file:///path")) == "file:///path"
-rw-r--r-- | lib/elixir/lib/uri.ex | 40 | ||||
-rw-r--r-- | lib/elixir/test/elixir/uri_test.exs | 11 |
2 files changed, 41 insertions, 10 deletions
diff --git a/lib/elixir/lib/uri.ex b/lib/elixir/lib/uri.ex index b00401644..c1cfa68ad 100644 --- a/lib/elixir/lib/uri.ex +++ b/lib/elixir/lib/uri.ex @@ -454,18 +454,38 @@ defmodule URI do def parse(string) when is_binary(string) do # From https://tools.ietf.org/html/rfc3986#appendix-B + # Parts: 12 3 4 5 6 7 8 9 regex = ~r{^(([a-z][a-z0-9\+\-\.]*):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?}i parts = Regex.run(regex, string) - destructure [_, _, scheme, _, authority, path, query_with_question_mark, _, _, fragment], + destructure [ + _full, + # 1 + _scheme_with_colon, + # 2 + scheme, + # 3 + authority_with_slashes, + # 4 + _authority, + # 5 + path, + # 6 + query_with_question_mark, + # 7 + _query, + # 8 + _fragment_with_hash, + # 9 + fragment + ], parts scheme = nillify(scheme) - authority = nillify(authority) path = nillify(path) query = nillify_query(query_with_question_mark) - {userinfo, host, port} = split_authority(authority) + {authority, userinfo, host, port} = split_authority(authority_with_slashes) scheme = scheme && String.downcase(scheme) port = port || (scheme && default_port(scheme)) @@ -486,16 +506,24 @@ defmodule URI do defp nillify_query(_other), do: nil # Split an authority into its userinfo, host and port parts. - defp split_authority(string) do + defp split_authority("") do + {nil, nil, nil, nil} + end + + defp split_authority("//") do + {"", nil, "", nil} + end + + defp split_authority("//" <> authority) do regex = ~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/ - components = Regex.run(regex, string || "") + components = Regex.run(regex, authority) destructure [_, _, userinfo, host, _, port], components userinfo = nillify(userinfo) host = if nillify(host), do: host |> String.trim_leading("[") |> String.trim_trailing("]") port = if nillify(port), do: String.to_integer(port) - {userinfo, host, port} + {authority, userinfo, host, port} end # Regex.run returns empty strings sometimes. We want diff --git a/lib/elixir/test/elixir/uri_test.exs b/lib/elixir/test/elixir/uri_test.exs index 84da8ec29..5480e5017 100644 --- a/lib/elixir/test/elixir/uri_test.exs +++ b/lib/elixir/test/elixir/uri_test.exs @@ -116,13 +116,13 @@ defmodule URITest do test "works with \"file\" scheme" do expected_uri = %URI{ scheme: "file", - host: nil, + host: "", path: "/foo/bar/baz", userinfo: nil, query: nil, fragment: nil, port: nil, - authority: nil + authority: "" } assert URI.parse("file:///foo/bar/baz") == expected_uri @@ -179,8 +179,8 @@ defmodule URITest do test "works with LDAP scheme" do expected_uri = %URI{ scheme: "ldap", - host: nil, - authority: nil, + host: "", + authority: "", userinfo: nil, path: "/dc=example,dc=com", query: "?sub?(givenName=John)", @@ -331,6 +331,9 @@ defmodule URITest do assert to_string(URI.parse("http://google.com")) == "http://google.com" assert to_string(URI.parse("http://google.com:443")) == "http://google.com:443" assert to_string(URI.parse("https://google.com:443")) == "https://google.com" + assert to_string(URI.parse("file:/path")) == "file:/path" + assert to_string(URI.parse("file:///path")) == "file:///path" + assert to_string(URI.parse("file://///path")) == "file://///path" assert to_string(URI.parse("http://lol:wut@google.com")) == "http://lol:wut@google.com" assert to_string(URI.parse("http://google.com/elixir")) == "http://google.com/elixir" assert to_string(URI.parse("http://google.com?q=lol")) == "http://google.com?q=lol" |