cowboy_handler.erl 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. %% Copyright (c) 2011-2017, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. %% Handler middleware.
  15. %%
  16. %% Execute the handler given by the <em>handler</em> and <em>handler_opts</em>
  17. %% environment values. The result of this execution is added to the
  18. %% environment under the <em>result</em> value.
  19. -module(cowboy_handler).
  20. -behaviour(cowboy_middleware).
  21. -ifdef(OTP_RELEASE).
  22. -compile({nowarn_deprecated_function, [{erlang, get_stacktrace, 0}]}).
  23. -endif.
  24. -export([execute/2]).
  25. -export([terminate/4]).
  26. -callback init(Req, any())
  27. -> {ok | module(), Req, any()}
  28. | {module(), Req, any(), any()}
  29. when Req::cowboy_req:req().
  30. -callback terminate(any(), map(), any()) -> ok.
  31. -optional_callbacks([terminate/3]).
  32. -spec execute(Req, Env) -> {ok, Req, Env}
  33. when Req::cowboy_req:req(), Env::cowboy_middleware:env().
  34. execute(Req, Env=#{handler := Handler, handler_opts := HandlerOpts}) ->
  35. try Handler:init(Req, HandlerOpts) of
  36. {ok, Req2, State} ->
  37. Result = terminate(normal, Req2, State, Handler),
  38. {ok, Req2, Env#{result => Result}};
  39. {Mod, Req2, State} ->
  40. Mod:upgrade(Req2, Env, Handler, State);
  41. {Mod, Req2, State, Opts} ->
  42. Mod:upgrade(Req2, Env, Handler, State, Opts)
  43. catch Class:Reason ->
  44. terminate({crash, Class, Reason}, Req, HandlerOpts, Handler),
  45. erlang:raise(Class, Reason, erlang:get_stacktrace())
  46. end.
  47. -spec terminate(any(), Req | undefined, any(), module()) -> ok when Req::cowboy_req:req().
  48. terminate(Reason, Req, State, Handler) ->
  49. case erlang:function_exported(Handler, terminate, 3) of
  50. true ->
  51. Handler:terminate(Reason, Req, State);
  52. false ->
  53. ok
  54. end.