cowboy_handler.erl 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. %% Copyright (c) 2011-2014, 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(), hibernate}
  26. | {module(), Req, any(), timeout()}
  27. | {module(), Req, any(), timeout(), hibernate}
  28. when Req::cowboy_req:req().
  29. -callback terminate(any(), cowboy_req:req(), any()) -> ok.
  30. -optional_callbacks([terminate/3]).
  31. -spec execute(Req, Env) -> {ok, Req, Env}
  32. when Req::cowboy_req:req(), Env::cowboy_middleware:env().
  33. execute(Req, Env=#{handler := Handler, handler_opts := HandlerOpts}) ->
  34. try Handler:init(Req, HandlerOpts) of
  35. {ok, Req2, State} ->
  36. Result = terminate(normal, Req2, State, Handler),
  37. {ok, Req2, [{result, Result}|Env]};
  38. {Mod, Req2, State} ->
  39. Mod:upgrade(Req2, Env, Handler, State, infinity, run);
  40. {Mod, Req2, State, hibernate} ->
  41. Mod:upgrade(Req2, Env, Handler, State, infinity, hibernate);
  42. {Mod, Req2, State, Timeout} ->
  43. Mod:upgrade(Req2, Env, Handler, State, Timeout, run);
  44. {Mod, Req2, State, Timeout, hibernate} ->
  45. Mod:upgrade(Req2, Env, Handler, State, Timeout, hibernate)
  46. catch Class:Reason ->
  47. terminate({crash, Class, Reason}, Req, HandlerOpts, Handler),
  48. erlang:raise(Class, Reason, erlang:get_stacktrace())
  49. end.
  50. -spec terminate(any(), Req, any(), module()) -> ok when Req::cowboy_req:req().
  51. terminate(Reason, Req, State, Handler) ->
  52. case erlang:function_exported(Handler, terminate, 3) of
  53. true ->
  54. Handler:terminate(Reason, Req, State);
  55. false ->
  56. ok
  57. end.