Skip to content

Instantly share code, notes, and snippets.

@trbngr
Last active September 13, 2021 16:46
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 trbngr/024e30cba704885a68105b91fbda514e to your computer and use it in GitHub Desktop.
Save trbngr/024e30cba704885a68105b91fbda514e to your computer and use it in GitHub Desktop.
Absinthe Handle Exceptions
defmodule Middleware.HandleExceptions do
require Logger
alias Absinthe.Resolution
alias Ecto.Query.CastError
alias AbsintheErrorPayload.ChangesetParser
alias Ecto.{InvalidChangesetError, NoResultsError, StaleEntryError}
def handle_exceptions(middleware_spec) do
fn resolution, config ->
middleware_spec
|> wrap_middleware(resolution, config)
|> execute(resolution)
end
end
defp wrap_middleware({{mod, fun}, config}, resolution, _config) do
fn -> apply(mod, fun, [resolution, config]) end
end
defp wrap_middleware({mod, config}, resolution, _config) do
fn -> apply(mod, :call, [resolution, config]) end
end
defp wrap_middleware(mod, resolution, config) when is_atom(mod) do
fn -> apply(mod, :call, [resolution, config]) end
end
defp wrap_middleware(fun, resolution, config) when is_function(fun, 2) do
fn -> fun.(resolution, config) end
end
defp execute(fun, res) do
fun.()
rescue
e in CastError ->
type = if e.type === :binary_id, do: :uuid, else: e.type
error = [message: "Invalid argument", type: type, value: e.value, status: 400]
Resolution.put_result(res, {:error, error})
_ in NoResultsError ->
error = [message: "Not found", status: 404]
Resolution.put_result(res, {:error, error})
e in StaleEntryError ->
Resolution.put_result(
res,
{:error, [message: "Not found.", status: 404, detail: Exception.message(e)]}
)
e in InvalidChangesetError ->
errors =
e.changeset
|> ChangesetParser.extract_messages()
|> Enum.map(&"#{&1.field} #{&1.message}")
Resolution.put_result(res, {:error, errors})
e ->
Logger.error("Unexpected error", error: e, stacktrace: __STACKTRACE__)
Resolution.put_result(res, {:error, Exception.message(e)})
end
end
defmodule MySchema do
...
def middleware(middleware, _field, _object) do
Enum.map(middleware, &Middleware.HandleExceptions.handle_exceptions/1)
end
...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment