From cc2e084d456c99b3d71f09c08f516195b6015dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 27 Aug 2012 12:46:42 +0200 Subject: Update behaviours for R15B+ This effectively drops the R14B compatibility. The cowboy_req:req() type will be introduced in a future commit. It refers to the #http_req{} record. --- src/cowboy_app.erl | 5 --- src/cowboy_clock.erl | 7 --- src/cowboy_http_handler.erl | 54 +++++++++++------------ src/cowboy_http_websocket_handler.erl | 60 -------------------------- src/cowboy_loop_handler.erl | 57 ++++++++++++++++++++++++ src/cowboy_sup.erl | 7 --- src/cowboy_websocket_handler.erl | 81 +++++++++++++++++++++++++++++++++++ 7 files changed, 165 insertions(+), 106 deletions(-) delete mode 100644 src/cowboy_http_websocket_handler.erl create mode 100644 src/cowboy_loop_handler.erl create mode 100644 src/cowboy_websocket_handler.erl (limited to 'src') diff --git a/src/cowboy_app.erl b/src/cowboy_app.erl index 5ed1180..180d400 100644 --- a/src/cowboy_app.erl +++ b/src/cowboy_app.erl @@ -20,15 +20,10 @@ -export([start/2]). -export([stop/1]). --type application_start_type() :: normal - | {takeover, node()} | {failover, node()}. - %% API. --spec start(application_start_type(), any()) -> {ok, pid()}. start(_Type, _Args) -> cowboy_sup:start_link(). --spec stop(any()) -> ok. stop(_State) -> ok. diff --git a/src/cowboy_clock.erl b/src/cowboy_clock.erl index d8d220e..e29b640 100644 --- a/src/cowboy_clock.erl +++ b/src/cowboy_clock.erl @@ -107,7 +107,6 @@ rfc2109(LocalTime) -> %% gen_server. %% @private --spec init([]) -> {ok, #state{}}. init([]) -> ?TABLE = ets:new(?TABLE, [set, protected, named_table, {read_concurrency, true}]), @@ -118,8 +117,6 @@ init([]) -> {ok, #state{universaltime=T, rfc1123=B, tref=TRef}}. %% @private --spec handle_call(_, _, State) - -> {reply, ignored, State} | {stop, normal, stopped, State}. handle_call(stop, _From, State=#state{tref=TRef}) -> {ok, cancel} = timer:cancel(TRef), {stop, normal, stopped, State}; @@ -127,12 +124,10 @@ handle_call(_Request, _From, State) -> {reply, ignored, State}. %% @private --spec handle_cast(_, State) -> {noreply, State}. handle_cast(_Msg, State) -> {noreply, State}. %% @private --spec handle_info(_, State) -> {noreply, State}. handle_info(update, #state{universaltime=Prev, rfc1123=B1, tref=TRef}) -> T = erlang:universaltime(), B2 = update_rfc1123(B1, Prev, T), @@ -142,12 +137,10 @@ handle_info(_Info, State) -> {noreply, State}. %% @private --spec terminate(_, _) -> ok. terminate(_Reason, _State) -> ok. %% @private --spec code_change(_, State, _) -> {ok, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. diff --git a/src/cowboy_http_handler.erl b/src/cowboy_http_handler.erl index de7c025..d686f30 100644 --- a/src/cowboy_http_handler.erl +++ b/src/cowboy_http_handler.erl @@ -12,37 +12,37 @@ %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -%% @doc Handler for HTTP requests. +%% @doc Behaviour for short-lived HTTP handlers. %% -%% HTTP handlers must implement three callbacks: init/3, -%% handle/2 and terminate/2, called one after another in -%% that order. +%% init/3 allows you to initialize a state for all subsequent +%% callbacks, and indicate to Cowboy whether you accept to handle the +%% request or want to shutdown without handling it, in which case the +%% handle/2 call will simply be skipped. %% -%% init/3 is meant for initialization. It receives information about -%% the transport and protocol used, along with the handler options from the -%% dispatch list, and allows you to upgrade the protocol if needed. You can -%% define a request-wide state here. +%% handle/2 allows you to handle the request. It receives the +%% state previously defined. %% -%% handle/2 is meant for handling the request. It receives the -%% request and the state previously defined. +%% terminate/2 allows you to clean up. It receives the state +%% previously defined. %% -%% terminate/2 is meant for cleaning up. It also receives the -%% request and the state previously defined. -%% -%% You do not have to read the request body or even send a reply if you do -%% not need to. Cowboy will properly handle these cases and clean-up afterwards. -%% In doubt it'll simply close the connection. -%% -%% Note that when upgrading the connection to WebSocket you do not need to -%% define the handle/2 and terminate/2 callbacks. +%% There is no required operation to perform in any of these callbacks +%% other than returning the proper values. Make sure you always return +%% the last modified Req so that Cowboy has the up to date information +%% about the request. -module(cowboy_http_handler). --export([behaviour_info/1]). +-type opts() :: any(). +-type state() :: any(). -%% @private --spec behaviour_info(_) - -> undefined | [{handle, 2} | {init, 3} | {terminate, 2}, ...]. -behaviour_info(callbacks) -> - [{init, 3}, {handle, 2}, {terminate, 2}]; -behaviour_info(_Other) -> - undefined. +-callback init({atom(), http}, Req, opts()) + -> {ok, Req, state()} + | {loop, Req, state()} + | {loop, Req, state(), hibernate} + | {loop, Req, state(), timeout()} + | {loop, Req, state(), timeout(), hibernate} + | {shutdown, Req, state()} + | {upgrade, protocol, module()} + when Req::cowboy_req:req(). +-callback handle(Req, State) -> {ok, Req, State} + when Req::cowboy_req:req(), State::state(). +-callback terminate(cowboy_req:req(), state()) -> ok. diff --git a/src/cowboy_http_websocket_handler.erl b/src/cowboy_http_websocket_handler.erl deleted file mode 100644 index 4947302..0000000 --- a/src/cowboy_http_websocket_handler.erl +++ /dev/null @@ -1,60 +0,0 @@ -%% Copyright (c) 2011-2012, Loïc Hoguin -%% -%% Permission to use, copy, modify, and/or distribute this software for any -%% purpose with or without fee is hereby granted, provided that the above -%% copyright notice and this permission notice appear in all copies. -%% -%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -%% @doc Handler for HTTP WebSocket requests. -%% -%% WebSocket handlers must implement four callbacks: websocket_init/3, -%% websocket_handle/3, websocket_info/3 and -%% websocket_terminate/3. These callbacks will only be called if the -%% connection is upgraded to WebSocket in the HTTP handler's init/3 -%% callback. They are then called in that order, although -%% websocket_handle/3 will be called for each packet received, -%% and websocket_info for each message received. -%% -%% websocket_init/3 is meant for initialization. It receives -%% information about the transport and protocol used, along with the handler -%% options from the dispatch list. You can define a request-wide state here. -%% If you are going to want to compact the request, you should probably do it -%% here. -%% -%% websocket_handle/3 receives the data from the socket. It can reply -%% something, do nothing or close the connection. -%% -%% websocket_info/3 receives messages sent to the process. It has -%% the same reply format as websocket_handle/3 described above. Note -%% that unlike in a gen_server, when websocket_info/3 -%% replies something, it is always to the socket, not to the process that -%% originated the message. -%% -%% websocket_terminate/3 is meant for cleaning up. It also receives -%% the request and the state previously defined, along with a reason for -%% termination. -%% -%% All of websocket_init/3, websocket_handle/3 and -%% websocket_info/3 can decide to hibernate the process by adding -%% an extra element to the returned tuple, containing the atom -%% hibernate. Doing so helps save memory and improve CPU usage. --module(cowboy_http_websocket_handler). - --export([behaviour_info/1]). - -%% @private --spec behaviour_info(_) - -> undefined | [{websocket_handle, 3} | {websocket_info, 3} - | {websocket_init, 3} | {websocket_terminate, 3}, ...]. -behaviour_info(callbacks) -> - [{websocket_init, 3}, {websocket_handle, 3}, - {websocket_info, 3}, {websocket_terminate, 3}]; -behaviour_info(_Other) -> - undefined. diff --git a/src/cowboy_loop_handler.erl b/src/cowboy_loop_handler.erl new file mode 100644 index 0000000..5ff86cf --- /dev/null +++ b/src/cowboy_loop_handler.erl @@ -0,0 +1,57 @@ +%% Copyright (c) 2011-2012, Loïc Hoguin +%% +%% Permission to use, copy, modify, and/or distribute this software for any +%% purpose with or without fee is hereby granted, provided that the above +%% copyright notice and this permission notice appear in all copies. +%% +%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +%% @doc Behaviour for long-lived HTTP handlers. +%% +%% init/3 allows you to initialize a state for all subsequent +%% callbacks, and indicate to Cowboy whether you accept to handle the +%% request or want to shutdown without handling it, in which case the +%% receive loop and info/3 calls will simply be skipped. +%% +%% info/3 allows you to handle the messages this process will +%% receive. It receives the message and the state previously defined. +%% It can decide to stop the receive loop or continue receiving. +%% +%% terminate/2 allows you to clean up. It receives the state +%% previously defined. +%% +%% There is no required operation to perform in any of these callbacks +%% other than returning the proper values. Make sure you always return +%% the last modified Req so that Cowboy has the up to date information +%% about the request. +%% +%% It is recommended to use hibernate if this process is not going to +%% receive a lot of messages. It is also recommended to use a timeout +%% value so that the connection gets closed after a long period of +%% inactivity. +-module(cowboy_loop_handler). + +-type opts() :: any(). +-type state() :: any(). + +-callback init({atom(), http}, Req, opts()) + -> {ok, Req, state()} + | {loop, Req, state()} + | {loop, Req, state(), hibernate} + | {loop, Req, state(), timeout()} + | {loop, Req, state(), timeout(), hibernate} + | {shutdown, Req, state()} + | {upgrade, protocol, module()} + when Req::cowboy_req:req(). +-callback info(any(), Req, State) + -> {ok, Req, State} + | {loop, Req, State} + | {loop, Req, State, hibernate} + when Req::cowboy_req:req(), State::state(). +-callback terminate(cowboy_req:req(), state()) -> ok. diff --git a/src/cowboy_sup.erl b/src/cowboy_sup.erl index 8ce02f0..00fcc5e 100644 --- a/src/cowboy_sup.erl +++ b/src/cowboy_sup.erl @@ -32,13 +32,6 @@ start_link() -> %% supervisor. --spec init([]) -> {'ok', {{'one_for_one', 10, 10}, [{ - any(), {atom() | tuple(), atom(), 'undefined' | [any()]}, - 'permanent' | 'temporary' | 'transient', - 'brutal_kill' | 'infinity' | non_neg_integer(), - 'supervisor' | 'worker', - 'dynamic' | [atom() | tuple()]}] -}}. init([]) -> Procs = [{cowboy_clock, {cowboy_clock, start_link, []}, permanent, 5000, worker, [cowboy_clock]}], diff --git a/src/cowboy_websocket_handler.erl b/src/cowboy_websocket_handler.erl new file mode 100644 index 0000000..34749ba --- /dev/null +++ b/src/cowboy_websocket_handler.erl @@ -0,0 +1,81 @@ +%% Copyright (c) 2011-2012, Loïc Hoguin +%% +%% Permission to use, copy, modify, and/or distribute this software for any +%% purpose with or without fee is hereby granted, provided that the above +%% copyright notice and this permission notice appear in all copies. +%% +%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +%% @doc Handler for HTTP WebSocket requests. +%% +%% WebSocket handlers must implement five callbacks: init/3, +%% websocket_init/3, websocket_handle/3, +%% websocket_info/3 and websocket_terminate/3. +%% These callbacks will only be called if the connection is upgraded +%% to WebSocket in the HTTP handler's init/3 callback. +%% They are then called in that order, although websocket_handle/3 +%% will be called for each packet received, and websocket_info +%% for each message received. +%% +%% websocket_init/3 is meant for initialization. It receives +%% information about the transport and protocol used, along with the handler +%% options from the dispatch list. You can define a request-wide state here. +%% If you are going to want to compact the request, you should probably do it +%% here. +%% +%% websocket_handle/3 receives the data from the socket. It can reply +%% something, do nothing or close the connection. +%% +%% websocket_info/3 receives messages sent to the process. It has +%% the same reply format as websocket_handle/3 described above. Note +%% that unlike in a gen_server, when websocket_info/3 +%% replies something, it is always to the socket, not to the process that +%% originated the message. +%% +%% websocket_terminate/3 is meant for cleaning up. It also receives +%% the request and the state previously defined, along with a reason for +%% termination. +%% +%% All of websocket_init/3, websocket_handle/3 and +%% websocket_info/3 can decide to hibernate the process by adding +%% an extra element to the returned tuple, containing the atom +%% hibernate. Doing so helps save memory and improve CPU usage. +-module(cowboy_websocket_handler). + +-type opts() :: any(). +-type state() :: any(). +-type terminate_reason() :: {normal, closed} + | {normal, timeout} + | {error, closed} + | {error, badframe} + | {error, atom()}. + +-callback websocket_init(atom(), Req, opts()) + -> {ok, Req, state()} + | {ok, Req, state(), hibernate} + | {ok, Req, state(), timeout()} + | {ok, Req, state(), timeout(), hibernate} + | {shutdown, Req} + when Req::cowboy_req:req(). +-callback websocket_handle({text | binary | ping | pong, binary()}, Req, State) + -> {ok, Req, State} + | {ok, Req, State, hibernate} + | {reply, {text | binary | ping | pong, binary()}, Req, State} + | {reply, {text | binary | ping | pong, binary()}, Req, State, hibernate} + | {shutdown, Req, State} + when Req::cowboy_req:req(), State::state(). +-callback websocket_info(any(), Req, State) + -> {ok, Req, State} + | {ok, Req, State, hibernate} + | {reply, {text | binary | ping | pong, binary()}, Req, State} + | {reply, {text | binary | ping | pong, binary()}, Req, State, hibernate} + | {shutdown, Req, State} + when Req::cowboy_req:req(), State::state(). +-callback websocket_terminate(terminate_reason(), cowboy_req:req(), state()) + -> ok. -- cgit v1.2.3