Skip to content

Instantly share code, notes, and snippets.

@abitdodgy
Created May 15, 2016 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abitdodgy/a6c58ae088614cb55b8b51c585c4bf86 to your computer and use it in GitHub Desktop.
Save abitdodgy/a6c58ae088614cb55b8b51c585c4bf86 to your computer and use it in GitHub Desktop.
API Version router using `send_resp` vs a custom exceptin.
defmodule Event.Plug.API.VersionRouter do
@default_api_version "1"
def init(options) do
case Keyword.fetch!(options, :versions) do
versions ->
for {version, router} <- versions, into: %{} do
{version, {router, router.init([])}}
end
end
end
def call(conn, options) do
case Map.fetch(options, get_api_version_from_conn(conn)) do
{:ok, {router, router_options}} ->
router.call(conn, router_options)
_ ->
raise InvalidAPIVersionError, conn: conn, valid_api_versions: Map.keys(options)
end
end
defp get_api_version_from_conn(conn) do
case Plug.Conn.get_req_header(conn, "api-version") do
[version] ->
version
_ ->
@default_api_version
end
end
defmodule InvalidAPIVersionError do
@moduledoc """
Exception raised when an invalid API version is passed in the `Api-Version` header.
"""
defexception plug_status: 422, message: "invalid API version", conn: nil
def exception(options) do
conn = Keyword.fetch!(options, :conn)
valid_api_versions = Keyword.fetch!(options, :valid_api_versions)
requested_version = Plug.Conn.get_req_header(conn, "api-version")
%InvalidAPIVersionError{
conn: conn,
message: "#{requested_version} is not a valid API version. Valid versions are: #{Enum.join(valid_api_versions, ", ")}"
}
end
end
end
defmodule Event.Plug.API.VersionRouter do
use Event.Web, :router
@default_version "1"
def init(options) do
case Keyword.fetch!(options, :versions) do
versions ->
for {version, router} <- versions, into: %{} do
{version, {router, router.init([])}}
end
end
end
def call(conn, options) do
version = get_api_version_from_conn(conn)
case Map.fetch(options, version) do
{:ok, {router, router_options}} ->
router.call(conn, router_options)
_ ->
send_resp conn, :unprocessable_entity,
"#{version} is not a valid API version. Valid versions are #{Map.keys(options) |> Enum.join(", ")}"
end
end
defp get_api_version_from_conn(conn) do
case Plug.Conn.get_req_header(conn, "api-version") do
[version] ->
version
_ ->
@default_version
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment