cowboy_loop.erl (4117B)
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 15 -module(cowboy_loop). 16 -behaviour(cowboy_sub_protocol). 17 18 -export([upgrade/4]). 19 -export([upgrade/5]). 20 -export([loop/4]). 21 22 -export([system_continue/3]). 23 -export([system_terminate/4]). 24 -export([system_code_change/4]). 25 26 -callback init(Req, any()) 27 -> {ok | module(), Req, any()} 28 | {module(), Req, any(), any()} 29 when Req::cowboy_req:req(). 30 31 -callback info(any(), Req, State) 32 -> {ok, Req, State} 33 | {ok, Req, State, hibernate} 34 | {stop, Req, State} 35 when Req::cowboy_req:req(), State::any(). 36 37 -callback terminate(any(), cowboy_req:req(), any()) -> ok. 38 -optional_callbacks([terminate/3]). 39 40 -spec upgrade(Req, Env, module(), any()) 41 -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]} 42 when Req::cowboy_req:req(), Env::cowboy_middleware:env(). 43 upgrade(Req, Env, Handler, HandlerState) -> 44 loop(Req, Env, Handler, HandlerState). 45 46 -spec upgrade(Req, Env, module(), any(), hibernate) 47 -> {suspend, ?MODULE, loop, [any()]} 48 when Req::cowboy_req:req(), Env::cowboy_middleware:env(). 49 upgrade(Req, Env, Handler, HandlerState, hibernate) -> 50 suspend(Req, Env, Handler, HandlerState). 51 52 -spec loop(Req, Env, module(), any()) 53 -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]} 54 when Req::cowboy_req:req(), Env::cowboy_middleware:env(). 55 %% @todo Handle system messages. 56 loop(Req=#{pid := Parent}, Env, Handler, HandlerState) -> 57 receive 58 %% System messages. 59 {'EXIT', Parent, Reason} -> 60 terminate(Req, Env, Handler, HandlerState, Reason); 61 {system, From, Request} -> 62 sys:handle_system_msg(Request, From, Parent, ?MODULE, [], 63 {Req, Env, Handler, HandlerState}); 64 %% Calls from supervisor module. 65 {'$gen_call', From, Call} -> 66 cowboy_children:handle_supervisor_call(Call, From, [], ?MODULE), 67 loop(Req, Env, Handler, HandlerState); 68 Message -> 69 call(Req, Env, Handler, HandlerState, Message) 70 end. 71 72 call(Req0, Env, Handler, HandlerState0, Message) -> 73 try Handler:info(Message, Req0, HandlerState0) of 74 {ok, Req, HandlerState} -> 75 loop(Req, Env, Handler, HandlerState); 76 {ok, Req, HandlerState, hibernate} -> 77 suspend(Req, Env, Handler, HandlerState); 78 {stop, Req, HandlerState} -> 79 terminate(Req, Env, Handler, HandlerState, stop) 80 catch Class:Reason:Stacktrace -> 81 cowboy_handler:terminate({crash, Class, Reason}, Req0, HandlerState0, Handler), 82 erlang:raise(Class, Reason, Stacktrace) 83 end. 84 85 suspend(Req, Env, Handler, HandlerState) -> 86 {suspend, ?MODULE, loop, [Req, Env, Handler, HandlerState]}. 87 88 terminate(Req, Env, Handler, HandlerState, Reason) -> 89 Result = cowboy_handler:terminate(Reason, Req, HandlerState, Handler), 90 {ok, Req, Env#{result => Result}}. 91 92 %% System callbacks. 93 94 -spec system_continue(_, _, {Req, Env, module(), any()}) 95 -> {ok, Req, Env} | {suspend, ?MODULE, loop, [any()]} 96 when Req::cowboy_req:req(), Env::cowboy_middleware:env(). 97 system_continue(_, _, {Req, Env, Handler, HandlerState}) -> 98 loop(Req, Env, Handler, HandlerState). 99 100 -spec system_terminate(any(), _, _, {Req, Env, module(), any()}) 101 -> {ok, Req, Env} when Req::cowboy_req:req(), Env::cowboy_middleware:env(). 102 system_terminate(Reason, _, _, {Req, Env, Handler, HandlerState}) -> 103 terminate(Req, Env, Handler, HandlerState, Reason). 104 105 -spec system_code_change(Misc, _, _, _) -> {ok, Misc} 106 when Misc::{cowboy_req:req(), cowboy_middleware:env(), module(), any()}. 107 system_code_change(Misc, _, _, _) -> 108 {ok, Misc}.