'Idiom to construct a URI with a query string in Elixir
I'm wondering what the most idiomatic way is to use URI to add a query string to a base URI in Elixir.
I'm currently doing something like this:
iex(1)> base = "http://example.com/endpoint"
"http://example.com/endpoint"
iex(2)> query_string = URI.encode_query(foo: "bar")
"foo=bar"
iex(3)> uri_string = URI.parse(base) |> Map.put(:query, query_string) |> URI.to_string
"http://example.com/endpoint?foo=bar"
But was wondering if there is a cleaner way to set the query string. I know about URI.merge/2, but I don't think a query string is a valid URI, so that's probably not approriate here (the ? will not be added).
I could also do something like:
uri_string = %URI{ URI.parse(base) | query: query_string } |> URI.to_string
But I'm wondering if there is a simpler or clearer method I've missed.
Solution 1:[1]
I think your first example, with some formatting, reads pretty well:
uri_string =
base_url
|> URI.parse()
|> Map.put(:query, URI.encode_query(params))
|> URI.to_string()
I'm not aware of other idioms/shortcuts.
Solution 2:[2]
I'm not sure that it's more idiomatic but you can do simple string interpolation if you know the string you're trying to build.
uri_string = "#{base}?#{query_string}"
Solution 3:[3]
As of Elixir 1.13, URI.new!/1 is available, which unlike URI.parse/1 also validates the URI.
It's also safer to use Map.replace!/3 instead of Map.put/3, to ensure you do not make a typo of the query key of the URI struct.
"http://example.com/endpoint"
|> URI.new!()
|> Map.replace!(:query, URI.encode_query(foo: "bar"))
|> URI.to_string()
You can also use then/2 (added in Elixir 1.12) to make use of struct sematics if you prefer. The benefit of this is that you will get a compile time, rather than a runtime error if you get the query key wrong.
"http://example.com/endpoint"
|> URI.new!()
|> then(&%URI{&1 | query: URI.encode_query(foo: "bar")})
|> URI.to_string()
Output for both examples:
"http://example.com/endpoint?foo=bar"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | zwippie |
| Solution 2 | Ronan Boiteau |
| Solution 3 |
