Problems with URL in a configuration for Ecto

I’m trying to use an URL configuration for a database connection in Ecto.

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: {:system, "DB_URL"},
  pool_size: 20

And then run an application with DB_URL=ecto://postgres:mypwdWith#Symbol/some_db
I get Ecto.InvalidURLError invalid url ..., path should be a database name error.

I checked source code and saw, that this URL string parses using url |> URI.decode() |> URI.parse()
I tried it and saw that after # symbol everything parses as a url fragment. I encoded this symbol to %23 and tried. But received the same result, because it decodes before parses.

Looks like I can’t use # symbol in a DB password, Am I missing something?

1 Like

Did you try escaping it with backslash?

1 Like

Thanks for the reply, but your suggestion doesn’t work.

1 Like

You can use # symbol in your database password, but if you’re using URL as your connection string, that character separates the URL itself from fragment id, see https://en.wikipedia.org/wiki/Fragment_identifier

edit: Sorry if the above is obvious, I’m not sure whether that’s a bug or feature :wink:

1 Like

Weird it is being decoded, but if it is only doing it once maybe you could double encode it? “%2523” for the “#”?

1 Like

I just had the same idea but I think it won’t work. Worth a shot. A long shot.

1 Like

I tried this also. It creates a valid URL to parse, but password is wrong.

1 Like

Decoding before we parse it is wrong. It is fixed in master, can you please give it a try? If it works I can backport it to 2.1.

3 Likes

It works now. Thanks for a super fast fix!
Next time I’ll make a PR instead of bother people on the forum :slight_smile:

2 Likes

Currently running ecto 2.2.8 and facing the same issue with a password ending in ‘#’.
Am I missing something?

Thanks in advance,

Mark

My issue was solved with the fix. So probably it’s something else.

I get the exact same error message.
Have removed the # from the password to get around the issue for the time being.

I have very similar problem but with ? my
db_url=“ecto://my_user:ad?fd8@127.0.0.1:5432/mydabase”
db_url |> URI.encode() |> URI.decode() |> URI.parse

%URI{
  authority: "my_user:ad",
  fragment: nil,
  host: "my_user",
  path: nil,
  port: nil,
  query: "fd8@127.0.0.1:5432/mydabase",
  scheme: "ecto",
  userinfo: nil
}

Is there way to overcome this? I have no control of the password generation and the database to which I want to connect.

1 Like

URI’s have rules of which characters are allowed where and any not allowed ones need to be encoded. The userinfo section requires ? to be percent encoded:

URI.encode("ad?fd8", &URI.char_unreserved?/1)
"ad%3Ffd8"

https://www.rfc-editor.org/rfc/rfc3986#section-3.2.1

1 Like

Thank you! It works perfectly!