summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-12-05 21:49:32 +0100
committerEric Meadows-Jönsson <eric.meadows.jonsson@gmail.com>2019-12-06 03:55:20 +0100
commit6f513f3bab8fd27b0b72ba5c94355b219da61805 (patch)
tree07735de3f69234ee70b3530dbd107edd4c94ca51
parent0a33059a10092960219983caafe4aad96eb5a980 (diff)
downloadelixir-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.ex40
-rw-r--r--lib/elixir/test/elixir/uri_test.exs11
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"