5

I'm trying to implement a custom plug for API versioning. Now I need to be able to match a value passed with the requests headers (i.e. Accept: application/vnd.app.v1+json). So far I have implemented the following:

defmodule UsersApi.Plugs.APIVersion do
  import Plug.Conn

  @versions ["application/vnd.app.v1+json", "application/vnd.app.v2+json"]

  def init(version), do: version

  def call(%{req_headers: %{"accept" => version}} = conn, _) when version in @versions do
    assign(conn, :version, version)
  end

  def call(conn, version), do: assign(conn, :version, version)
end

This is not currently working and falling through to the second call/2 which is designed as a fallback when no accept header is specified. How can I match with request headers?

Dogbert
  • 212,659
  • 41
  • 396
  • 397
tomasbasham
  • 1,695
  • 2
  • 18
  • 37
  • `req_headers` is a list; you can't pattern match like this. You can use `get_req_header/2` though. – Dogbert Feb 19 '17 at 21:36

1 Answers1

18

req_headers is a list but you're pattern matching it like a map, which always fails, and all calls to call/2 end up in the fallback. You can use get_req_header/2 for this:

def call(conn, default_version) do
  version = case get_req_header(conn, "accept") do
    [version] when version in @versions -> version
    _ -> default_version
  end
  assign(conn, :version, version)
end
Dogbert
  • 212,659
  • 41
  • 396
  • 397