Phoenix params removes + from the param value. How to prevent this?


Phoenix removes + from the email address in the query params. This is from the conn:

query_params: %{
    "encemail" => "",
    "verificid" => "f866b2ea169f4809971dcd97bbc8e17e7f82fe350d7e57e4eabd5c5f1cd97308"
  query_string: ""

I think here José Valim is suggesting that this is because of URI decoding. However, in iex if I try the following, the + is not stripped:

iex(9)> URI.decode("")
iex(10)> URI.encode("")

How do I keep the + in the email? I am URI encoding the email address when I create the link using URI.encode(email).

1 Like

This may have something to do with Phoenix.Param protocol.

Checkout: Phoenix.Param — Phoenix v1.6.6

It includes information about custom parameters.

Thank you @muelthe. Unfortunately, I could not understand how to use the information at that link. It appears my issue is a different one.

Anyhow, for now I am using the following workaround: instead of using URI.encode to encode the email and then trying to use URI.decode later when reading back the email, using Base.encode64 and Base.decode64 work well. Once I Base.decode64 the email is received correctly.

The keys and values in the query string are expected to be form-urlencoded, based on the behavior of an HTML form when using method="GET".

The corresponding function in URI is URI.decode_www_form which transforms + to a space.

FWIW, the @ character is also usually encoded in query parameters as it is reserved.


@curioustolearn my bad. I had just finished reading about it in the Programming Phoenix book and it seemed like a good place to start :grin:

@al2o3cr thanks for the explanation.

Thank you for the explanation @al2o3cr. I will use URI.decode_www_form.
Just for understanding this better, why does URI.encode not percent escape the + and @ symbols. Isn’t that what it is for?

Thank you.

RFC 3986 section 2.2 defines three classes of characters in URLs:

  • “unreserved” characters, that can always appear without escaping
  • “reserved” characters, which are intended for use as delimiters
  • (implicitly) all other characters, which are not allowed to appear unescaped at all

+ and @ are “reserved”.

URI.encode only encodes characters in that third category, while URI.encode_www_form also encodes “reserved” characters.


Thank you very much for the clear explanation.