From c2f50e4504da649ae4a5ffa543a95fca4e0cbb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Wojtasik?= Date: Thu, 16 Dec 2021 16:50:34 +0100 Subject: [PATCH] Catch any unexpected graphql internal crash --- src/mongoose_graphql.erl | 8 +++++++- src/mongoose_graphql/mongoose_graphql_errors.erl | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/mongoose_graphql.erl b/src/mongoose_graphql.erl index 440667ca49..ee5bd333c4 100644 --- a/src/mongoose_graphql.erl +++ b/src/mongoose_graphql.erl @@ -72,7 +72,13 @@ execute(Ep, #{document := Doc, {ok, graphql:execute(Ep, Ctx2, Ast2)} catch throw:{error, Err} -> - {error, Err} + {error, Err}; + Class:Reason:Stacktrace -> + Err = #{what => graphql_internal_crash, + class => Class, reason => Reason, + stacktrace => Stacktrace}, + ?LOG_ERROR(Err), + {error, internal_crash} end. %% @doc Execute selected operation on a given endpoint with authorization. diff --git a/src/mongoose_graphql/mongoose_graphql_errors.erl b/src/mongoose_graphql/mongoose_graphql_errors.erl index 3f6f0c050b..7d60932008 100644 --- a/src/mongoose_graphql/mongoose_graphql_errors.erl +++ b/src/mongoose_graphql/mongoose_graphql_errors.erl @@ -5,7 +5,10 @@ -ignore_xref([format_error/1, err/2, crash/2]). +-type err_msg() :: #{message := binary(), extensions => map(), path => list()}. + %% callback invoked when resolver returns error tuple +-spec err(map(), term()) -> err_msg(). err(_Ctx, domain_not_found) -> #{message => <<"Given domain does not exist">>, extensions => #{code => resolver_error}}; err(_Ctx, ErrorTerm) -> @@ -13,11 +16,13 @@ err(_Ctx, ErrorTerm) -> extensions => #{code => resolver_error}}. %% callback invoked when resolver crashes +-spec crash(map(), term()) -> err_msg(). crash(_Ctx, #{type := Type}) -> #{message => <<"Unexpected ", Type/binary, " resolver crash">>, extensions => #{code => resolver_crash}}. %% @doc Format error that occurred in any phase including HTTP request decoding. +-spec format_error(term())-> {integer(), err_msg()}. format_error(#{phase := Phase, error_term := Term}) when Phase =:= authorize; Phase =:= decode; Phase =:= parse -> @@ -28,7 +33,12 @@ format_error(#{error_term := _, phase := Phase} = Err) when Phase =:= execute; Phase =:= type_check; Phase =:= validate; Phase =:= uncategorized -> - {400, graphql:format_errors(#{}, [Err])}; + [ErrMsg] = graphql:format_errors(#{}, [Err]), + {400, ErrMsg}; +format_error(internal_crash) -> + Msg = #{message => <<"GraphQL Internal Server Error">>, + extensions => #{code => internal_server_error}}, + {500, Msg}; format_error(Err) -> Msg = #{extensions => #{code => uncathegorized}, message => iolist_to_binary(io_lib:format("~p", [Err]))},