Skip to content

Commit 1348278

Browse files
committed
username and password now supports percent encoding/decoding
1 parent 40b027a commit 1348278

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

lib/mongo/url_parser.ex

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
defmodule Mongo.UrlParser do
2-
@moduledoc "Mongo connection URL parsing util"
2+
@moduledoc """
3+
Mongo connection URL parsing util
4+
5+
[See](https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options) for the complete list of options.
6+
7+
"""
38

49
@mongo_url_regex ~r/^mongodb(?<srv>\+srv)?:\/\/((?<username>[^:]+):(?<password>[^@]+)@)?(?<seeds>[^\/]+)(\/(?<database>[^?]+))?(\?(?<options>.*))?$/
510

6-
# https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options
11+
#https://docs.mongodb.com/manual/reference/connection-string/#connections-connection-options
712
@mongo_options %{
813
# Path options
914
"username" => :string,
@@ -90,17 +95,22 @@ defmodule Mongo.UrlParser do
9095
opts
9196

9297
value ->
93-
key =
94-
key
95-
|> Macro.underscore()
96-
|> String.to_atom()
98+
key = key
99+
|> Macro.underscore()
100+
|> String.to_atom()
101+
102+
value = decode_password(key, value)
97103

98104
Keyword.put(opts, @driver_option_map[key] || key, value)
99105
end
100106
end
101107

102108
defp add_option(_other, acc), do: acc
103109

110+
defp decode_password(:username, value), do: URI.decode_www_form(value)
111+
defp decode_password(:password, value), do: URI.decode_www_form(value)
112+
defp decode_password(_other, value), do: value
113+
104114
defp parse_query_options(opts, %{"options" => options}) when is_binary(options) do
105115
options
106116
|> String.split("&")

test/mongo/url_parser_test.exs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,21 @@ defmodule Mongo.UrlParserTest do
7272
]
7373
end
7474
end
75+
76+
test "encoded password" do
77+
78+
real_username = "@:/skøl:@/"
79+
real_password = "@æœ{}%e()}@"
80+
81+
encoded_username = URI.encode_www_form(real_username)
82+
encoded_password = URI.encode_www_form(real_password)
83+
url = "mongodb://#{encoded_username}:#{encoded_password}@mymongodbserver:27017/admin"
84+
opts = UrlParser.parse_url(url: url)
85+
password = Keyword.get(opts, :password)
86+
username = Keyword.get(opts, :username)
87+
assert password == real_password
88+
assert username == real_username
89+
end
90+
7591
end
7692
end

0 commit comments

Comments
 (0)