Error in pattern matching

If the Authorization header in conn is “Bearer abcde” and I have the following code:

"Bearer " <> token = get_req_header(conn, "authorization")
IO.puts token

I am expecting “abcde” in my iex console, but instead I have these:

** (MatchError) no match of right hand side value: ["Bearer abcde"]

What am I doing wrong with pattern matching?

Plug.Conn.get_req_header/2 does always return a list of values. So you need to match on a list of binaries:

["Bearer " <> token] = get_req_header(conn, "authorization")

Still, this might not be perfect, as you said the value is only "abcde" and not "Bearer abcde". Also in my opinion you should accept "bearer" as well.

2 Likes

Wow!
Yea @NobbZ I really missed saying that Authorization is “Bearer abcde”.
Thanks for bearing with my newbieness but I am accumulating the lessons thru realizations and you response definitely added to it.
Will be correcting my question above for the rest of the newbies to refer to.
Thanks so much @NobbZ!

By the way I would like to clarify what you really mean when you said I should accept “bearer” as well?

Well, literally that… I have seen implementations with the type beeing sent with a capital B as first letter and with a lower case b. Unless you controll all API consumers, you should make it a low effort to talk to the API.

2 Likes

@NobbZ, is it possible to do something like ["{B|b}earer " <> token] in pattern matching?

No.

I usually split on the first space (String.split(header_value, " ", parts: 2)) and then String.downcase the head before matching.

Ah! Thanks @NobbZ!

@NobbZ,

I have been trying to find a good way of doing what you suggested but I feel the code I come up with is way far from idiomatic like:

header_value = "Bearer abcdef"
[head | token] = String.split(header_value, " ", parts: 2)
head = String.downcase(head)
header_value = head <> " " <> token
["bearer " <> token] = header_value

Is it possible to ask for your opinion as to how to come up with something more idiomatic with what you are suggesting?

If you just want to get the token back:

def get_bearer_token(header_value) do
  with [method, data] <- String.split("Bearer abcdef", " ", parts: 2),
    "bearer" <- String.downcase(method) do
    {:ok, data}
  else
    {:error, :no_bearer}
  end
end

Other ways with a delegating function with a pipe and some helpers are thinkable. But I prefer some monadic with here.

2 Likes

Though I still have to try deciphering that, I would have to thank you again for sharing your thoughts. Gracias!