cowboy_handler.erl 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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. -export([execute/2]).
  22. -export([terminate/4]).
  23. -callback init(Req, any())
  24. -> {ok | module(), Req, any()}
  25. | {module(), Req, any(), any()}
  26. when Req::cowboy_req:req().
  27. -callback terminate(any(), cowboy_req:req(), any()) -> ok.
  28. -optional_callbacks([terminate/3]).
  29. -spec execute(Req, Env) -> {ok, Req, Env}
  30. when Req::cowboy_req:req(), Env::cowboy_middleware:env().
  31. execute(Req, Env=#{handler := Handler, handler_opts := HandlerOpts}) ->
  32. try Handler:init(Req, HandlerOpts) of
  33. {ok, Req2, State} ->
  34. Result = terminate(normal, Req2, State, Handler),
  35. {ok, Req2, Env#{result => Result}};
  36. {Mod, Req2, State} ->
  37. Mod:upgrade(Req2, Env, Handler, State);
  38. {Mod, Req2, State, Opts} ->
  39. Mod:upgrade(Req2, Env, Handler, State, Opts)
  40. catch Class:Reason ->
  41. terminate({crash, Class, Reason}, Req, HandlerOpts, Handler),
  42. erlang:raise(Class, Reason, erlang:get_stacktrace())
  43. end.
  44. -spec terminate(any(), Req | undefined, any(), module()) -> ok when Req::cowboy_req:req().
  45. terminate(Reason, Req, State, Handler) ->
  46. case erlang:function_exported(Handler, terminate, 3) of
  47. true ->
  48. Handler:terminate(Reason, Req, State);
  49. false ->
  50. ok
  51. end.