Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Improve types for R15B+

Removes compatibility with versions < R15B.

Also use one export per line to improve future diffs.
  • Loading branch information...
commit eb0d73274fad8ac9fb15f1631055f168e1505284 1 parent 3d2aad3
Loïc Hoguin authored
View
2  Makefile
@@ -52,7 +52,7 @@ intct:
build-plt:
@$(DIALYZER) --build_plt --output_plt .$(PROJECT).plt \
- --apps kernel stdlib sasl inets crypto public_key ssl
+ --apps kernel stdlib sasl tools inets crypto public_key ssl deps/ranch
dialyze:
@$(DIALYZER) --src src --plt .$(PROJECT).plt --no_native \
View
4 rebar.config
@@ -1,6 +1,6 @@
{deps, [
- {ranch, "0.2.0",
- {git, "git://github.com/extend/ranch.git", {tag, "0.2.0"}}}
+ {ranch, "0.2.1",
+ {git, "git://github.com/extend/ranch.git", {tag, "0.2.1"}}}
]}.
{erl_opts, [
%% bin_opt_info,
View
4 rebar.tests.config
@@ -1,7 +1,7 @@
{cover_enabled, true}.
{deps, [
- {ranch, "0.2.0",
- {git, "git://github.com/extend/ranch.git", {tag, "0.2.0"}}},
+ {ranch, "0.2.1",
+ {git, "git://github.com/extend/ranch.git", {tag, "0.2.1"}}},
{proper, "1.0",
{git, "git://github.com/manopapad/proper.git", {tag, "v1.0"}}}
]}.
View
34 src/cowboy_app.erl
@@ -16,38 +16,14 @@
-module(cowboy_app).
-behaviour(application).
--export([start/2, stop/1, profile_output/0]). %% API.
-
--type application_start_type() :: normal
- | {takeover, node()} | {failover, node()}.
+%% API.
+-export([start/2]).
+-export([stop/1]).
%% API.
--spec start(application_start_type(), any()) -> {ok, pid()}.
-start(_Type, _Args) ->
- consider_profiling(),
+start(_, _) ->
cowboy_sup:start_link().
--spec stop(any()) -> ok.
-stop(_State) ->
+stop(_) ->
ok.
-
--spec profile_output() -> ok.
-profile_output() ->
- eprof:stop_profiling(),
- eprof:log("procs.profile"),
- eprof:analyze(procs),
- eprof:log("total.profile"),
- eprof:analyze(total).
-
-%% Internal.
-
--spec consider_profiling() -> profiling | not_profiling.
-consider_profiling() ->
- case application:get_env(profile) of
- {ok, true} ->
- {ok, _Pid} = eprof:start(),
- eprof:start_profiling([self()]);
- _ ->
- not_profiling
- end.
View
8 src/cowboy_bstr.erl
@@ -15,8 +15,12 @@
%% @doc Binary string manipulation.
-module(cowboy_bstr).
--export([to_lower/1]). %% Binary strings.
--export([char_to_lower/1, char_to_upper/1]). %% Characters.
+%% Binary strings.
+-export([to_lower/1]).
+
+%% Characters.
+-export([char_to_lower/1]).
+-export([char_to_upper/1]).
%% @doc Convert a binary string to lowercase.
-spec to_lower(binary()) -> binary().
View
29 src/cowboy_clock.erl
@@ -21,9 +21,19 @@
-module(cowboy_clock).
-behaviour(gen_server).
--export([start_link/0, stop/0, rfc1123/0, rfc2109/1]). %% API.
--export([init/1, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2, code_change/3]). %% gen_server.
+%% API.
+-export([start_link/0]).
+-export([stop/0]).
+-export([rfc1123/0]).
+-export([rfc2109/1]).
+
+%% gen_server.
+-export([init/1]).
+-export([handle_call/3]).
+-export([handle_cast/2]).
+-export([handle_info/2]).
+-export([terminate/2]).
+-export([code_change/3]).
-record(state, {
universaltime = undefined :: undefined | calendar:datetime(),
@@ -61,8 +71,8 @@ rfc1123() ->
%% HTTP responses.
-spec rfc2109(calendar:datetime()) -> binary().
rfc2109(LocalTime) ->
- {{YYYY,MM,DD},{Hour,Min,Sec}} =
- case calendar:local_time_to_universal_time_dst(LocalTime) of
+ {{YYYY,MM,DD},{Hour,Min,Sec}} = case
+ calendar:local_time_to_universal_time_dst(LocalTime) of
[Gmt] -> Gmt;
[_,Gmt] -> Gmt;
[] ->
@@ -87,12 +97,9 @@ rfc2109(LocalTime) ->
SecBin = pad_int(Sec),
WeekDay = weekday(Wday),
Month = month(MM),
- <<WeekDay/binary, ", ",
- DayBin/binary, " ", Month/binary, " ",
- YearBin/binary, " ",
- HourBin/binary, ":",
- MinBin/binary, ":",
- SecBin/binary, " GMT">>.
+ << WeekDay/binary, ", ", DayBin/binary, " ", Month/binary, " ",
+ YearBin/binary, " ", HourBin/binary, ":", MinBin/binary, ":",
+ SecBin/binary, " GMT">>.
%% gen_server.
View
5 src/cowboy_cookies.erl
@@ -17,7 +17,10 @@
-module(cowboy_cookies).
--export([parse_cookie/1, cookie/3, cookie/2]). %% API.
+%% API.
+-export([parse_cookie/1]).
+-export([cookie/3]).
+-export([cookie/2]).
%% Types.
-type kv() :: {Name::binary(), Value::binary()}.
View
9 src/cowboy_dispatcher.erl
@@ -16,7 +16,10 @@
%% @doc Dispatch requests according to a hostname and path.
-module(cowboy_dispatcher).
--export([split_host/1, split_path/2, match/3]). %% API.
+%% API.
+-export([split_host/1]).
+-export([split_path/2]).
+-export([match/3]).
-type bindings() :: list({atom(), binary()}).
-type tokens() :: list(binary()).
@@ -25,7 +28,9 @@
-type dispatch_rule() :: {Host::match_rule(), Path::dispatch_path()}.
-type dispatch_rules() :: list(dispatch_rule()).
--export_type([bindings/0, tokens/0, dispatch_rules/0]).
+-export_type([bindings/0]).
+-export_type([tokens/0]).
+-export_type([dispatch_rules/0]).
-include_lib("eunit/include/eunit.hrl").
View
44 src/cowboy_http.erl
@@ -17,18 +17,38 @@
-module(cowboy_http).
%% Parsing.
--export([list/2, nonempty_list/2, content_type/1, media_range/2, conneg/2,
- language_range/2, entity_tag_match/1, expectation/2, params/2,
- http_date/1, rfc1123_date/1, rfc850_date/1, asctime_date/1,
- whitespace/2, digits/1, token/2, token_ci/2, quoted_string/2]).
+-export([list/2]).
+-export([nonempty_list/2]).
+-export([content_type/1]).
+-export([media_range/2]).
+-export([conneg/2]).
+-export([language_range/2]).
+-export([entity_tag_match/1]).
+-export([expectation/2]).
+-export([params/2]).
+-export([http_date/1]).
+-export([rfc1123_date/1]).
+-export([rfc850_date/1]).
+-export([asctime_date/1]).
+-export([whitespace/2]).
+-export([digits/1]).
+-export([token/2]).
+-export([token_ci/2]).
+-export([quoted_string/2]).
%% Decoding.
--export([te_chunked/2, te_identity/2, ce_identity/1]).
+-export([te_chunked/2]).
+-export([te_identity/2]).
+-export([ce_identity/1]).
%% Interpretation.
--export([connection_to_atom/1, version_to_binary/1,
- urldecode/1, urldecode/2, urlencode/1,
- urlencode/2, x_www_form_urlencoded/2]).
+-export([connection_to_atom/1]).
+-export([version_to_binary/1]).
+-export([urldecode/1]).
+-export([urldecode/2]).
+-export([urlencode/1]).
+-export([urlencode/2]).
+-export([x_www_form_urlencoded/2]).
-type method() :: 'OPTIONS' | 'GET' | 'HEAD'
| 'POST' | 'PUT' | 'DELETE' | 'TRACE' | binary().
@@ -53,7 +73,12 @@
-type headers() :: [{header(), iodata()}].
-type status() :: non_neg_integer() | binary().
--export_type([method/0, uri/0, version/0, header/0, headers/0, status/0]).
+-export_type([method/0]).
+-export_type([uri/0]).
+-export_type([version/0]).
+-export_type([header/0]).
+-export_type([headers/0]).
+-export_type([status/0]).
-include_lib("eunit/include/eunit.hrl").
@@ -827,7 +852,6 @@ unhex(C) when C >= $A, C =< $F -> C - $A + 10;
unhex(C) when C >= $a, C =< $f -> C - $a + 10;
unhex(_) -> error.
-
%% @doc URL encode a string binary.
%% @equiv urlencode(Bin, [])
-spec urlencode(binary()) -> binary().
View
54 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.
View
57 src/cowboy_loop_handler.erl
@@ -0,0 +1,57 @@
+%% Copyright (c) 2011-2012, Loïc Hoguin <essen@ninenines.eu>
+%%
+%% 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.
View
3  src/cowboy_multipart.erl
@@ -27,7 +27,8 @@
-type end_of_part() :: {end_of_part, cont(more(part_result()))}.
-type disposition() :: {binary(), [{binary(), binary()}]}.
--export([parser/1, content_disposition/1]).
+-export([parser/1]).
+-export([content_disposition/1]).
-include_lib("eunit/include/eunit.hrl").
View
9 src/cowboy_protocol.erl
@@ -34,8 +34,13 @@
%% @see cowboy_http_handler
-module(cowboy_protocol).
--export([start_link/4]). %% API.
--export([init/4, parse_request/1, handler_loop/3]). %% FSM.
+%% API.
+-export([start_link/4]).
+
+%% FSM.
+-export([init/4]).
+-export([parse_request/1]).
+-export([handler_loop/3]).
-include("http.hrl").
-include_lib("eunit/include/eunit.hrl").
View
94 src/cowboy_req.erl
@@ -21,38 +21,73 @@
%% some lazy evaluation and cache results where possible.
-module(cowboy_req).
--export([
- method/1, version/1, peer/1, peer_addr/1,
- host/1, host_info/1, raw_host/1, port/1,
- path/1, path_info/1, raw_path/1,
- qs_val/2, qs_val/3, qs_vals/1, raw_qs/1,
- binding/2, binding/3, bindings/1,
- header/2, header/3, headers/1,
- parse_header/2, parse_header/3,
- cookie/2, cookie/3, cookies/1,
- meta/2, meta/3
-]). %% Request API.
-
--export([
- has_body/1, body_length/1, init_stream/4, stream_body/1,
- skip_body/1, body/1, body/2, body_qs/1,
- multipart_data/1, multipart_skip/1
-]). %% Request Body API.
-
--export([
- set_resp_cookie/4, set_resp_header/3, set_resp_body/2,
- set_resp_body_fun/3, has_resp_header/2, has_resp_body/1,
- reply/2, reply/3, reply/4,
- chunked_reply/2, chunked_reply/3, chunk/2,
- upgrade_reply/3
-]). %% Response API.
-
--export([
- compact/1, transport/1
-]). %% Misc API.
+%% Request API.
+-export([method/1]).
+-export([version/1]).
+-export([peer/1]).
+-export([peer_addr/1]).
+-export([host/1]).
+-export([host_info/1]).
+-export([raw_host/1]).
+-export([port/1]).
+-export([path/1]).
+-export([path_info/1]).
+-export([raw_path/1]).
+-export([qs_val/2]).
+-export([qs_val/3]).
+-export([qs_vals/1]).
+-export([raw_qs/1]).
+-export([binding/2]).
+-export([binding/3]).
+-export([bindings/1]).
+-export([header/2]).
+-export([header/3]).
+-export([headers/1]).
+-export([parse_header/2]).
+-export([parse_header/3]).
+-export([cookie/2]).
+-export([cookie/3]).
+-export([cookies/1]).
+-export([meta/2]).
+-export([meta/3]).
+
+%% Request Body API.
+-export([has_body/1]).
+-export([body_length/1]).
+-export([init_stream/4]).
+-export([stream_body/1]).
+-export([skip_body/1]).
+-export([body/1]).
+-export([body/2]).
+-export([body_qs/1]).
+-export([multipart_data/1]).
+-export([multipart_skip/1]).
+
+%% Response API.
+-export([set_resp_cookie/4]).
+-export([set_resp_header/3]).
+-export([set_resp_body/2]).
+-export([set_resp_body_fun/3]).
+-export([has_resp_header/2]).
+-export([has_resp_body/1]).
+-export([reply/2]).
+-export([reply/3]).
+-export([reply/4]).
+-export([chunked_reply/2]).
+-export([chunked_reply/3]).
+-export([chunk/2]).
+-export([upgrade_reply/3]).
+
+%% Misc API.
+-export([compact/1]).
+-export([transport/1]).
-include("http.hrl").
+%% @todo opaque
+-type req() :: #http_req{}.
+-export_type([req/0]).
+
%% Request API.
%% @doc Return the HTTP method of the request.
@@ -640,7 +675,6 @@ set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) ->
set_resp_body(Body, Req) ->
{ok, Req#http_req{resp_body=Body}}.
-
%% @doc Add a body function to the response.
%%
%% The response body may also be set to a content-length - stream-function pair.
View
29 src/cowboy_static.erl
@@ -177,9 +177,15 @@
-export([init/3]).
%% cowboy_rest callbacks
--export([rest_init/2, allowed_methods/2, malformed_request/2,
- resource_exists/2, forbidden/2, last_modified/2, generate_etag/2,
- content_types_provided/2, file_contents/2]).
+-export([rest_init/2]).
+-export([allowed_methods/2]).
+-export([malformed_request/2]).
+-export([resource_exists/2]).
+-export([forbidden/2]).
+-export([last_modified/2]).
+-export([generate_etag/2]).
+-export([content_types_provided/2]).
+-export([file_contents/2]).
%% internal
-export([path_to_mimetypes/2]).
@@ -199,12 +205,10 @@
etag_fun :: {fun(([etagarg()], T) ->
undefined | {strong | weak, binary()}), T}}).
-
%% @private Upgrade from HTTP handler to REST handler.
init({_Transport, http}, _Req, _Opts) ->
{upgrade, protocol, cowboy_rest}.
-
%% @private Set up initial state of REST handler.
-spec rest_init(#http_req{}, list()) -> {ok, #http_req{}, #state{}}.
rest_init(Req, Opts) ->
@@ -239,7 +243,6 @@ rest_init(Req, Opts) ->
end,
{ok, Req1, State}.
-
%% @private Only allow GET and HEAD requests on files.
-spec allowed_methods(#http_req{}, #state{}) ->
{[atom()], #http_req{}, #state{}}.
@@ -254,7 +257,6 @@ malformed_request(Req, #state{filepath=error}=State) ->
malformed_request(Req, State) ->
{false, Req, State}.
-
%% @private Check if the resource exists under the document root.
-spec resource_exists(#http_req{}, #state{}) ->
{boolean(), #http_req{}, #state{}}.
@@ -263,7 +265,6 @@ resource_exists(Req, #state{fileinfo={error, _}}=State) ->
resource_exists(Req, #state{fileinfo={ok, Fileinfo}}=State) ->
{Fileinfo#file_info.type =:= regular, Req, State}.
-
%% @private
%% Access to a file resource is forbidden if it exists and the local node does
%% not have permission to read it. Directory listings are always forbidden.
@@ -277,14 +278,12 @@ forbidden(Req, #state{fileinfo={error, _}}=State) ->
forbidden(Req, #state{fileinfo={ok, #file_info{access=Access}}}=State) ->
{not (Access =:= read orelse Access =:= read_write), Req, State}.
-
%% @private Read the time a file system system object was last modified.
-spec last_modified(#http_req{}, #state{}) ->
{calendar:datetime(), #http_req{}, #state{}}.
last_modified(Req, #state{fileinfo={ok, #file_info{mtime=Modified}}}=State) ->
{Modified, Req, State}.
-
%% @private Generate the ETag header value for this file.
%% The ETag header value is only generated if the resource is a file that
%% exists in document root.
@@ -300,7 +299,6 @@ generate_etag(Req, #state{fileinfo={_, #file_info{type=regular, inode=INode,
generate_etag(Req, State) ->
{undefined, Req, State}.
-
%% @private Return the content type of a file.
-spec content_types_provided(#http_req{}, #state{}) -> tuple().
content_types_provided(Req, #state{filepath=Filepath,
@@ -309,7 +307,6 @@ content_types_provided(Req, #state{filepath=Filepath,
|| T <- MimetypesFun(Filepath, MimetypesData)],
{Mimetypes, Req, State}.
-
%% @private Return a function that writes a file directly to the socket.
-spec file_contents(#http_req{}, #state{}) -> tuple().
file_contents(Req, #state{filepath=Filepath,
@@ -318,7 +315,6 @@ file_contents(Req, #state{filepath=Filepath,
Writefile = content_function(Transport, Socket, Filepath),
{{stream, Filesize, Writefile}, Req, State}.
-
%% @private Return a function writing the contents of a file to a socket.
%% The function returns the number of bytes written to the socket to enable
%% the calling function to determine if the expected number of bytes were
@@ -338,7 +334,6 @@ content_function(Transport, Socket, Filepath) ->
fun() -> sendfile(Socket, Filepath) end
end.
-
%% @private Sendfile fallback function.
-spec sfallback(module(), inet:socket(), binary()) -> {sent, non_neg_integer()}.
sfallback(Transport, Socket, Filepath) ->
@@ -359,7 +354,6 @@ sfallback(Transport, Socket, File, Sent) ->
end
end.
-
%% @private Wrapper for sendfile function.
-spec sendfile(inet:socket(), binary()) -> {sent, non_neg_integer()}.
sendfile(Socket, Filepath) ->
@@ -400,7 +394,6 @@ check_path([H|T]) ->
nomatch -> check_path(T)
end.
-
%% @private Join the the directory and request paths.
-spec join_paths(dirpath(), [binary()]) -> binary().
join_paths([H|_]=Dirpath, Filepath) when is_integer(H) ->
@@ -412,7 +405,6 @@ join_paths(Dirpath, Filepath) when is_binary(Dirpath) ->
join_paths([], Filepath) ->
filename:join(Filepath).
-
%% @private Return the path to the priv/ directory of an application.
-spec priv_dir_path(atom()) -> string().
priv_dir_path(App) ->
@@ -428,7 +420,6 @@ priv_dir_mod(Mod) ->
File -> filename:join([filename:dirname(File),"../priv"])
end.
-
%% @private Use application/octet-stream as the default mimetype.
%% If a list of extension - mimetype pairs are provided as the mimetypes
%% an attempt to find the mimetype using the file extension. If no match
@@ -453,7 +444,6 @@ path_to_mimetypes_(Ext, Extensions) ->
default_mimetype() ->
[{<<"application">>, <<"octet-stream">>, []}].
-
%% @private Do not send ETag headers in the default configuration.
-spec no_etag_function([etagarg()], undefined) -> undefined.
no_etag_function(_Args, undefined) ->
@@ -469,7 +459,6 @@ attr_etag_function(Args, Attrs) ->
end || Attr <- Attrs],
{strong, list_to_binary([H|T])}.
-
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-define(_eq(E, I), ?_assertEqual(E, I)).
View
7 src/cowboy_sup.erl
@@ -29,13 +29,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]}],
View
4 src/cowboy_websocket.erl
@@ -295,7 +295,6 @@ websocket_data(State, Req, HandlerState,
websocket_data(State, Req, HandlerState, _Data) ->
websocket_close(State, Req, HandlerState, {error, badframe}).
-
-spec websocket_data(#state{}, #http_req{}, any(), non_neg_integer(),
non_neg_integer(), non_neg_integer(), non_neg_integer(),
non_neg_integer(), binary(), binary()) -> closed.
@@ -339,7 +338,7 @@ websocket_data(State=#state{frag_state={nofin, Opcode, Payloads}}, Req,
%% control messages MUST NOT use 7+16 bits or 7+64 bits payload length prefixes
websocket_data(State, Req, HandlerState, _Fin, _Rsv, Opcode, _Mask, PayloadLen,
_Rest, _Data) when Opcode >= 8, PayloadLen > 125 ->
- websocket_close(State, Req, HandlerState, {error, protocol});
+ websocket_close(State, Req, HandlerState, {error, badframe});
%% unfragmented message. unmask and dispatch the message.
websocket_data(State=#state{version=Version}, Req, HandlerState, _Fin=1, _Rsv=0,
Opcode, Mask, PayloadLen, Rest, Data) when Version =/= 0 ->
@@ -350,7 +349,6 @@ websocket_data(State, Req, HandlerState, _Fin, _Rsv, _Opcode, _Mask,
_PayloadLen, _Rest, _Data) ->
websocket_close(State, Req, HandlerState, {error, badframe}).
-
%% hybi routing depending on whether unmasking is needed.
-spec websocket_before_unmask(#state{}, #http_req{}, any(), binary(),
binary(), opcode(), 0 | 1, non_neg_integer() | undefined) -> closed.
View
57 src/cowboy_http_websocket_handler.erl → 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.
View
13 test/http_SUITE.erl
@@ -127,16 +127,15 @@ groups() ->
].
init_per_suite(Config) ->
- application:start(inets),
- application:start(ranch),
- application:start(cowboy),
+ ok = application:start(inets),
+ ok = application:start(ranch),
+ ok = application:start(cowboy),
Config.
end_per_suite(_Config) ->
- application:stop(cowboy),
- application:stop(ranch),
- application:stop(inets),
- ok.
+ ok = application:stop(cowboy),
+ ok = application:stop(ranch),
+ ok = application:stop(inets).
init_per_group(http, Config) ->
Port = 33080,
View
2  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]).
View
2  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]).
View
2  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]).
View
2  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]).
Please sign in to comment.
Something went wrong with that request. Please try again.