aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_app.erl5
-rw-r--r--src/cowboy_clock.erl7
-rw-r--r--src/cowboy_http_handler.erl54
-rw-r--r--src/cowboy_loop_handler.erl57
-rw-r--r--src/cowboy_sup.erl7
-rw-r--r--src/cowboy_websocket_handler.erl (renamed from src/cowboy_http_websocket_handler.erl)57
6 files changed, 123 insertions, 64 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.