Don't collapse HTTPoison response headers
Today I learned…
2020-04-05
The ergonomics of Keyword.t and proplist-like data structures in Elixir are less than ideal. In particular, keyword lists as function arguments preclude advanced pattern-matching in function heads.
Recently, I’ve grown fond of the following pattern: I write multi-parameter functions is such a way that callers can provide either a keyword-list or a map, but internally I always transform this parameter into a map.
This allows for much more precision in determining which arguments are required, and which can be filled in with some default value.
For example:
def picky_function(args) do
%{a: required, b: required} = args = Enum.into(args, %{})
c = Map.get(args, :c, "sane default")
d = Map.get(args, :d, 12345)
This practice led me to underestimate situations where proplist-like datastructures are there for a reason. Case in point: %HTTPoison.Response.headers
I’d been accessing the response headers through my headers =
Enum.into(headers, %{})
utility pattern, but it turns out this is absolutely
the wrong thing to do for Set-Cookie
headers. There may be more than one
Set-Cookie
coming back with the server response. I’d been handling only one
cookie in my Elixir client program, because there could only exist one
"Set-Cookie"
key in the args
map.
TIL: Always be ready to handle multiple Set-Cookie
headers in an HTTPoison
response struct, and never ever flatten them into a map.
This is also documented in the HTTPoison repo.