Hi Floris, thanks for the proposal!

Unfortunately this is a bit more complicated than expected.

First of all, the current implementation is not in violation of RFC3986.
%20 is a valid escaping of spaces in query strings. As far as I know,
RFC3986 does not explicitly mention that + is equivalent to a space.
Furthermore, earlier specifications, such as RFC2396
<https://www.ietf.org/rfc/rfc2396.txt>, did not allow + in query strings at
all.

Only later on W3C specified that + is reserved to mean spaces
<https://www.w3.org/Addressing/URL/uri-spec.html> to be compatible with the
general usage of URLs - which browsers eventually standardized on. However,
at this point, the damage was done. For example, for mailto links, your
mail client may not rewrite + to spaces, while it will certainly handle
percent encoded spaces.

In other words, if you want to guarantee the space will be treated as
space, %20 is the best choice. So I would say String.replace/3 is the way
to go unless there is a quote in RFC3986 which suggests or advocates for
using + as the escaping of spaces in query strings.

Finally, it is important to remember that escaping of URI segments for
paths and query strings use distinct algorithms
<http://stephane.epardaud.fr/articles/2009-02-03-what-every-web-developer-must-know-about-url-encoding.html#Thereservedcharactersarenotwhatyouthinktheyare>
(which is why the function is called encode_query).


On Fri, Jan 29, 2021 at 10:59 AM Floris Huetink <[email protected]>
wrote:

> Hi,
>
> I've been using `URI.encode_query/1` to convert a key/value map to a query
> string to be appended to a URL (as GET parameters).
>
> As it turns out, `URI.encode_query/1` encodes differently than
> `URI.encode/2`, particularly in the case of spaces ("+" instead of "%20").
> For more context, please see the comment thread here:
>
> https://github.com/elixir-lang/elixir/pull/2392
>
> For me, it was non-obvious that I better *not* use `encode_query` to
> encode a URL-appending query string. I tried using `URI.encode/2` instead,
> as this provides RFC3986 encoding, but this simply behaves differently, in
> the sense that it takes string input, not an Enumerable.
>
> Given the above, I'd like to propose the addition of `URI.encode_query/2`,
> where the second argument should allow the user to specify which type of
> encoding should be used.
> Default encoding should be the existing `:www_form` encoding (I'm not sure
> if there is an official RFC for www-form-urlencoded? If so, we should use
> that)
> One should be able to replace this with RFC3986, e.g. like so:
>
> URI.encode_query(%{foo: "bar"}, :rfc3986)
>
> This should produce a query string with spaces encoded as "%20" instead of
> "+" (and possibly other differences).
>
> An alternative approach could be to use an `opts` Keyword list:
>
> URI.encode_query(%{foo: "bar"}, encoding: :rfc3986)
>
> The latter approach could have the benefit of being able to add other
> options later (which I currently cannot think of, but others might).
>
> The general benefit for Elixir users would be to be able to encode Elixir
> data structures (typically maps) into RFC3986 compliant query strings
> without having to manually iterate over every item and/or patching the
> `URI.encode_query/1` result with quick-and-dirty solutions like
> `String.replace(query_string, "+", "%20")`.
>
> That's it. I'd love to hear feedback!
>
> – Floris
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/538f2618-dd14-4084-b6cc-dabb7a8f58e7n%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/538f2618-dd14-4084-b6cc-dabb7a8f58e7n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Jp6S_KwuQtZyWwKAJZBFJ14Q8CDGdwW0zz445thf7Wqw%40mail.gmail.com.

Reply via email to