diff options
-rw-r--r-- | src/cowboy_app.erl | 5 | ||||
-rw-r--r-- | src/cowboy_clock.erl | 7 | ||||
-rw-r--r-- | src/cowboy_http_handler.erl | 54 | ||||
-rw-r--r-- | src/cowboy_loop_handler.erl | 57 | ||||
-rw-r--r-- | src/cowboy_sup.erl | 7 | ||||
-rw-r--r-- | src/cowboy_websocket_handler.erl (renamed from src/cowboy_http_websocket_handler.erl) | 57 | ||||
-rw-r--r-- | test/http_handler_loop_timeout.erl | 1 | ||||
-rw-r--r-- | test/websocket_echo_handler.erl | 2 | ||||
-rw-r--r-- | test/websocket_handler.erl | 2 | ||||
-rw-r--r-- | test/websocket_handler_init_shutdown.erl | 2 | ||||
-rw-r--r-- | test/ws_timeout_hibernate_handler.erl | 2 |
11 files changed, 128 insertions, 68 deletions
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: <em>init/3</em>, -%% <em>handle/2</em> and <em>terminate/2</em>, called one after another in -%% that order. +%% <em>init/3</em> 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 +%% <em>handle/2</em> call will simply be skipped. %% -%% <em>init/3</em> 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. +%% <em>handle/2</em> allows you to handle the request. It receives the +%% state previously defined. %% -%% <em>handle/2</em> is meant for handling the request. It receives the -%% request and the state previously defined. +%% <em>terminate/2</em> allows you to clean up. It receives the state +%% previously defined. %% -%% <em>terminate/2</em> 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 <em>handle/2</em> and <em>terminate/2</em> 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_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 <[email protected]> +%% +%% 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. +%% +%% <em>init/3</em> 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 <em>info/3</em> calls will simply be skipped. +%% +%% <em>info/3</em> 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. +%% +%% <em>terminate/2</em> 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_http_websocket_handler.erl b/src/cowboy_websocket_handler.erl index 4947302..34749ba 100644 --- a/src/cowboy_http_websocket_handler.erl +++ b/src/cowboy_websocket_handler.erl @@ -14,13 +14,14 @@ %% @doc Handler for HTTP WebSocket requests. %% -%% WebSocket handlers must implement four callbacks: <em>websocket_init/3</em>, -%% <em>websocket_handle/3</em>, <em>websocket_info/3</em> and -%% <em>websocket_terminate/3</em>. These callbacks will only be called if the -%% connection is upgraded to WebSocket in the HTTP handler's <em>init/3</em> -%% callback. They are then called in that order, although -%% <em>websocket_handle/3</em> will be called for each packet received, -%% and <em>websocket_info</em> for each message received. +%% WebSocket handlers must implement five callbacks: <em>init/3</em>, +%% <em>websocket_init/3</em>, <em>websocket_handle/3</em>, +%% <em>websocket_info/3</em> and <em>websocket_terminate/3</em>. +%% These callbacks will only be called if the connection is upgraded +%% to WebSocket in the HTTP handler's <em>init/3</em> callback. +%% They are then called in that order, although <em>websocket_handle/3</em> +%% will be called for each packet received, and <em>websocket_info</em> +%% for each message received. %% %% <em>websocket_init/3</em> is meant for initialization. It receives %% information about the transport and protocol used, along with the handler @@ -45,16 +46,36 @@ %% <em>websocket_info/3</em> can decide to hibernate the process by adding %% an extra element to the returned tuple, containing the atom %% <em>hibernate</em>. Doing so helps save memory and improve CPU usage. --module(cowboy_http_websocket_handler). +-module(cowboy_websocket_handler). --export([behaviour_info/1]). +-type opts() :: any(). +-type state() :: any(). +-type terminate_reason() :: {normal, closed} + | {normal, timeout} + | {error, closed} + | {error, badframe} + | {error, atom()}. -%% @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. +-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. diff --git a/test/http_handler_loop_timeout.erl b/test/http_handler_loop_timeout.erl index 76d6ea8..0e8c78f 100644 --- a/test/http_handler_loop_timeout.erl +++ b/test/http_handler_loop_timeout.erl @@ -1,6 +1,7 @@ %% Feel free to use, reuse and abuse the code in this file. -module(http_handler_loop_timeout). +-behaviour(cowboy_loop_handler). -export([init/3, info/3, terminate/2]). init({_, http}, Req, _) -> diff --git a/test/websocket_echo_handler.erl b/test/websocket_echo_handler.erl index b06c1e7..f5905c8 100644 --- a/test/websocket_echo_handler.erl +++ b/test/websocket_echo_handler.erl @@ -2,7 +2,7 @@ -module(websocket_echo_handler). -behaviour(cowboy_http_handler). --behaviour(cowboy_http_websocket_handler). +-behaviour(cowboy_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). diff --git a/test/websocket_handler.erl b/test/websocket_handler.erl index abb4967..5a484a0 100644 --- a/test/websocket_handler.erl +++ b/test/websocket_handler.erl @@ -2,7 +2,7 @@ -module(websocket_handler). -behaviour(cowboy_http_handler). --behaviour(cowboy_http_websocket_handler). +-behaviour(cowboy_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). diff --git a/test/websocket_handler_init_shutdown.erl b/test/websocket_handler_init_shutdown.erl index aa9e056..9d6c475 100644 --- a/test/websocket_handler_init_shutdown.erl +++ b/test/websocket_handler_init_shutdown.erl @@ -2,7 +2,7 @@ -module(websocket_handler_init_shutdown). -behaviour(cowboy_http_handler). --behaviour(cowboy_http_websocket_handler). +-behaviour(cowboy_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). diff --git a/test/ws_timeout_hibernate_handler.erl b/test/ws_timeout_hibernate_handler.erl index 777948a..871a686 100644 --- a/test/ws_timeout_hibernate_handler.erl +++ b/test/ws_timeout_hibernate_handler.erl @@ -2,7 +2,7 @@ -module(ws_timeout_hibernate_handler). -behaviour(cowboy_http_handler). --behaviour(cowboy_http_websocket_handler). +-behaviour(cowboy_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). |