aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/autobahn_SUITE.erl12
-rwxr-xr-xtest/autobahn_SUITE_data/test.py4
-rw-r--r--test/chunked_handler.erl6
-rw-r--r--test/cover.spec1
-rw-r--r--test/eunit_SUITE.erl31
-rw-r--r--test/http_SUITE.erl282
-rw-r--r--test/http_handler.erl4
-rw-r--r--test/http_handler_echo_body.erl8
-rw-r--r--test/http_handler_errors.erl4
-rw-r--r--test/http_handler_init_shutdown.erl4
-rw-r--r--test/http_handler_long_polling.erl4
-rw-r--r--test/http_handler_loop_timeout.erl4
-rw-r--r--test/http_handler_multipart.erl4
-rw-r--r--test/http_handler_set_resp.erl4
-rw-r--r--test/http_handler_stream_body.erl18
-rw-r--r--test/rest_created_path_resource.erl35
-rw-r--r--test/rest_patch_resource.erl34
-rw-r--r--test/websocket_echo_handler.erl9
-rw-r--r--test/websocket_handler.erl9
-rw-r--r--test/websocket_handler_init_shutdown.erl9
-rw-r--r--test/ws_SUITE.erl137
-rw-r--r--test/ws_timeout_cancel_handler.erl9
-rw-r--r--test/ws_timeout_hibernate_handler.erl9
23 files changed, 426 insertions, 215 deletions
diff --git a/test/autobahn_SUITE.erl b/test/autobahn_SUITE.erl
index 9ae9d7a..61cf631 100644
--- a/test/autobahn_SUITE.erl
+++ b/test/autobahn_SUITE.erl
@@ -64,7 +64,7 @@ end_per_suite(_Config) ->
init_per_group(autobahn, Config) ->
Port = 33080,
cowboy:start_http(autobahn, 100, [{port, Port}], [
- {dispatch, init_dispatch()}
+ {env, [{dispatch, init_dispatch()}]}
]),
[{port, Port}|Config].
@@ -75,8 +75,8 @@ end_per_group(Listener, _Config) ->
%% Dispatch configuration.
init_dispatch() ->
- [{[<<"localhost">>], [
- {[<<"echo">>], websocket_echo_handler, []}]}].
+ cowboy_router:compile([{"localhost", [
+ {"/echo", websocket_echo_handler, []}]}]).
%% autobahn cases
@@ -92,7 +92,7 @@ run_tests(Config) ->
_ -> ok
end,
{ok, IndexHTML} = file:read_file(IndexFile),
- case binary:match(IndexHTML, <<"Fail">>) of
- {_, _} -> erlang:error(failed);
- nomatch -> ok
+ case length(binary:matches(IndexHTML, <<"case_failed">>)) > 2 of
+ true -> erlang:error(failed);
+ false -> ok
end.
diff --git a/test/autobahn_SUITE_data/test.py b/test/autobahn_SUITE_data/test.py
index c528c64..19c7669 100755
--- a/test/autobahn_SUITE_data/test.py
+++ b/test/autobahn_SUITE_data/test.py
@@ -10,7 +10,7 @@ AB_TESTS_PRIV = os.getenv("AB_TESTS_PRIV")
VIRTUALENV_URL = 'https://raw.github.com/pypa/virtualenv/master/virtualenv.py'
VIRTUALENV_BIN = os.path.join(AB_TESTS_ENV, "virtualenv.py")
-PIP_BIN = os.path.join(AB_TESTS_ENV, "bin", "pip")
+INSTALL_BIN = os.path.join(AB_TESTS_ENV, "bin", "easy_install")
def activate_env(env):
@@ -29,7 +29,7 @@ def install_env(env):
subprocess.check_call(["curl", "-sS", VIRTUALENV_URL, "-o", VIRTUALENV_BIN])
subprocess.check_call(["python", VIRTUALENV_BIN, env])
activate_env(env)
- subprocess.check_call([PIP_BIN, "install", "AutobahnTestSuite"])
+ subprocess.check_call([INSTALL_BIN, "http://pypi.python.org/packages/2.7/a/autobahntestsuite/autobahntestsuite-0.5.2-py2.7.egg#md5=f7480d4ca6ce4954ac05f59778de4bda"])
def client_config():
"""
diff --git a/test/chunked_handler.erl b/test/chunked_handler.erl
index 38305fd..e486afe 100644
--- a/test/chunked_handler.erl
+++ b/test/chunked_handler.erl
@@ -2,16 +2,18 @@
-module(chunked_handler).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_Transport, http}, Req, _Opts) ->
{ok, Req, undefined}.
handle(Req, State) ->
{ok, Req2} = cowboy_req:chunked_reply(200, Req),
+ timer:sleep(100),
cowboy_req:chunk("chunked_handler\r\n", Req2),
+ timer:sleep(100),
cowboy_req:chunk("works fine!", Req2),
{ok, Req2, State}.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/cover.spec b/test/cover.spec
new file mode 100644
index 0000000..9dba11c
--- /dev/null
+++ b/test/cover.spec
@@ -0,0 +1 @@
+{incl_app, cowboy, details}.
diff --git a/test/eunit_SUITE.erl b/test/eunit_SUITE.erl
new file mode 100644
index 0000000..a460890
--- /dev/null
+++ b/test/eunit_SUITE.erl
@@ -0,0 +1,31 @@
+%% Copyright (c) 2013, 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.
+
+-module(eunit_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+%% ct.
+-export([all/0]).
+
+%% Tests.
+-export([eunit/1]).
+
+%% ct.
+
+all() ->
+ [eunit].
+
+eunit(_) ->
+ ok = eunit:test({application, cowboy}).
diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl
index c90e585..afe62c3 100644
--- a/test/http_SUITE.erl
+++ b/test/http_SUITE.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011-2012, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2013, Loïc Hoguin <[email protected]>
%% Copyright (c) 2011, Anthony Ramine <[email protected]>
%%
%% Permission to use, copy, modify, and/or distribute this software for any
@@ -45,21 +45,26 @@
-export([nc_zero/1]).
-export([onrequest/1]).
-export([onrequest_reply/1]).
+-export([onresponse_capitalize/1]).
-export([onresponse_crash/1]).
-export([onresponse_reply/1]).
-export([pipeline/1]).
-export([rest_bad_accept/1]).
+-export([rest_created_path/1]).
-export([rest_expires/1]).
-export([rest_keepalive/1]).
-export([rest_keepalive_post/1]).
-export([rest_missing_get_callbacks/1]).
-export([rest_missing_put_callbacks/1]).
-export([rest_nodelete/1]).
+-export([rest_patch/1]).
-export([rest_resource_etags/1]).
-export([rest_resource_etags_if_none_match/1]).
-export([set_resp_body/1]).
-export([set_resp_header/1]).
-export([set_resp_overwrite/1]).
+-export([slowloris/1]).
+-export([slowloris2/1]).
-export([static_attribute_etag/1]).
-export([static_function_etag/1]).
-export([static_mimetypes_function/1]).
@@ -68,14 +73,24 @@
-export([static_test_file/1]).
-export([static_test_file_css/1]).
-export([stream_body_set_resp/1]).
+-export([stream_body_set_resp_close/1]).
-export([te_chunked/1]).
+-export([te_chunked_chopped/1]).
-export([te_chunked_delayed/1]).
-export([te_identity/1]).
%% ct.
all() ->
- [{group, http}, {group, https}, {group, onrequest}, {group, onresponse}].
+ [
+ {group, http},
+ {group, https},
+ {group, http_compress},
+ {group, https_compress},
+ {group, onrequest},
+ {group, onresponse},
+ {group, onresponse_capitalize}
+ ].
groups() ->
Tests = [
@@ -98,17 +113,21 @@ groups() ->
nc_zero,
pipeline,
rest_bad_accept,
+ rest_created_path,
rest_expires,
rest_keepalive,
rest_keepalive_post,
rest_missing_get_callbacks,
rest_missing_put_callbacks,
rest_nodelete,
+ rest_patch,
rest_resource_etags,
rest_resource_etags_if_none_match,
set_resp_body,
set_resp_header,
set_resp_overwrite,
+ slowloris,
+ slowloris2,
static_attribute_etag,
static_function_etag,
static_mimetypes_function,
@@ -117,13 +136,17 @@ groups() ->
static_test_file,
static_test_file_css,
stream_body_set_resp,
+ stream_body_set_resp_close,
te_chunked,
+ te_chunked_chopped,
te_chunked_delayed,
te_identity
],
[
{http, [], Tests},
{https, [], Tests},
+ {http_compress, [], Tests},
+ {https_compress, [], Tests},
{onrequest, [], [
onrequest,
onrequest_reply
@@ -131,11 +154,13 @@ groups() ->
{onresponse, [], [
onresponse_crash,
onresponse_reply
+ ]},
+ {onresponse_capitalize, [], [
+ onresponse_capitalize
]}
].
init_per_suite(Config) ->
- application:start(inets),
application:start(crypto),
application:start(ranch),
application:start(cowboy),
@@ -145,7 +170,6 @@ end_per_suite(_Config) ->
application:stop(cowboy),
application:stop(ranch),
application:stop(crypto),
- application:stop(inets),
ok.
init_per_group(http, Config) ->
@@ -153,7 +177,7 @@ init_per_group(http, Config) ->
Transport = ranch_tcp,
Config1 = init_static_dir(Config),
{ok, _} = cowboy:start_http(http, 100, [{port, Port}], [
- {dispatch, init_dispatch(Config1)},
+ {env, [{dispatch, init_dispatch(Config1)}]},
{max_keepalive, 50},
{timeout, 500}
]),
@@ -172,18 +196,51 @@ init_per_group(https, Config) ->
application:start(public_key),
application:start(ssl),
{ok, _} = cowboy:start_https(https, 100, Opts ++ [{port, Port}], [
- {dispatch, init_dispatch(Config1)},
+ {env, [{dispatch, init_dispatch(Config1)}]},
{max_keepalive, 50},
{timeout, 500}
]),
{ok, Client} = cowboy_client:init(Opts),
[{scheme, <<"https">>}, {port, Port}, {opts, Opts},
{transport, Transport}, {client, Client}|Config1];
-init_per_group(onrequest, Config) ->
+init_per_group(http_compress, Config) ->
Port = 33082,
Transport = ranch_tcp,
+ Config1 = init_static_dir(Config),
+ {ok, _} = cowboy:start_http(http_compress, 100, [{port, Port}], [
+ {compress, true},
+ {env, [{dispatch, init_dispatch(Config1)}]},
+ {max_keepalive, 50},
+ {timeout, 500}
+ ]),
+ {ok, Client} = cowboy_client:init([]),
+ [{scheme, <<"http">>}, {port, Port}, {opts, []},
+ {transport, Transport}, {client, Client}|Config1];
+init_per_group(https_compress, Config) ->
+ Port = 33083,
+ Transport = ranch_ssl,
+ Opts = [
+ {certfile, ?config(data_dir, Config) ++ "cert.pem"},
+ {keyfile, ?config(data_dir, Config) ++ "key.pem"},
+ {password, "cowboy"}
+ ],
+ Config1 = init_static_dir(Config),
+ application:start(public_key),
+ application:start(ssl),
+ {ok, _} = cowboy:start_https(https_compress, 100, Opts ++ [{port, Port}], [
+ {compress, true},
+ {env, [{dispatch, init_dispatch(Config1)}]},
+ {max_keepalive, 50},
+ {timeout, 500}
+ ]),
+ {ok, Client} = cowboy_client:init(Opts),
+ [{scheme, <<"https">>}, {port, Port}, {opts, Opts},
+ {transport, Transport}, {client, Client}|Config1];
+init_per_group(onrequest, Config) ->
+ Port = 33084,
+ Transport = ranch_tcp,
{ok, _} = cowboy:start_http(onrequest, 100, [{port, Port}], [
- {dispatch, init_dispatch(Config)},
+ {env, [{dispatch, init_dispatch(Config)}]},
{max_keepalive, 50},
{onrequest, fun onrequest_hook/1},
{timeout, 500}
@@ -192,25 +249,37 @@ init_per_group(onrequest, Config) ->
[{scheme, <<"http">>}, {port, Port}, {opts, []},
{transport, Transport}, {client, Client}|Config];
init_per_group(onresponse, Config) ->
- Port = 33083,
+ Port = 33085,
Transport = ranch_tcp,
{ok, _} = cowboy:start_http(onresponse, 100, [{port, Port}], [
- {dispatch, init_dispatch(Config)},
+ {env, [{dispatch, init_dispatch(Config)}]},
{max_keepalive, 50},
{onresponse, fun onresponse_hook/4},
{timeout, 500}
]),
{ok, Client} = cowboy_client:init([]),
[{scheme, <<"http">>}, {port, Port}, {opts, []},
+ {transport, Transport}, {client, Client}|Config];
+init_per_group(onresponse_capitalize, Config) ->
+ Port = 33086,
+ Transport = ranch_tcp,
+ {ok, _} = cowboy:start_http(onresponse_capitalize, 100, [{port, Port}], [
+ {env, [{dispatch, init_dispatch(Config)}]},
+ {max_keepalive, 50},
+ {onresponse, fun onresponse_capitalize_hook/4},
+ {timeout, 500}
+ ]),
+ {ok, Client} = cowboy_client:init([]),
+ [{scheme, <<"http">>}, {port, Port}, {opts, []},
{transport, Transport}, {client, Client}|Config].
-end_per_group(https, Config) ->
+end_per_group(Group, Config) when Group =:= https; Group =:= https_compress ->
cowboy:stop_listener(https),
application:stop(ssl),
application:stop(public_key),
end_static_dir(Config),
ok;
-end_per_group(http, Config) ->
+end_per_group(Group, Config) when Group =:= http; Group =:= http_compress ->
cowboy:stop_listener(http),
end_static_dir(Config);
end_per_group(Name, _) ->
@@ -220,54 +289,60 @@ end_per_group(Name, _) ->
%% Dispatch configuration.
init_dispatch(Config) ->
- [
- {[<<"localhost">>], [
- {[<<"chunked_response">>], chunked_handler, []},
- {[<<"init_shutdown">>], http_handler_init_shutdown, []},
- {[<<"long_polling">>], http_handler_long_polling, []},
- {[<<"headers">>, <<"dupe">>], http_handler,
+ cowboy_router:compile([
+ {"localhost", [
+ {"/chunked_response", chunked_handler, []},
+ {"/init_shutdown", http_handler_init_shutdown, []},
+ {"/long_polling", http_handler_long_polling, []},
+ {"/headers/dupe", http_handler,
[{headers, [{<<"connection">>, <<"close">>}]}]},
- {[<<"set_resp">>, <<"header">>], http_handler_set_resp,
+ {"/set_resp/header", http_handler_set_resp,
[{headers, [{<<"vary">>, <<"Accept">>}]}]},
- {[<<"set_resp">>, <<"overwrite">>], http_handler_set_resp,
+ {"/set_resp/overwrite", http_handler_set_resp,
[{headers, [{<<"server">>, <<"DesireDrive/1.0">>}]}]},
- {[<<"set_resp">>, <<"body">>], http_handler_set_resp,
+ {"/set_resp/body", http_handler_set_resp,
[{body, <<"A flameless dance does not equal a cycle">>}]},
- {[<<"stream_body">>, <<"set_resp">>], http_handler_stream_body,
+ {"/stream_body/set_resp", http_handler_stream_body,
[{reply, set_resp}, {body, <<"stream_body_set_resp">>}]},
- {[<<"static">>, '...'], cowboy_static,
+ {"/stream_body/set_resp_close",
+ http_handler_stream_body, [
+ {reply, set_resp_close},
+ {body, <<"stream_body_set_resp_close">>}]},
+ {"/static/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{mimetypes, [{<<".css">>, [<<"text/css">>]}]}]},
- {[<<"static_mimetypes_function">>, '...'], cowboy_static,
+ {"/static_mimetypes_function/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{mimetypes, {fun(Path, data) when is_binary(Path) ->
[<<"text/html">>] end, data}}]},
- {[<<"handler_errors">>], http_handler_errors, []},
- {[<<"static_attribute_etag">>, '...'], cowboy_static,
+ {"/handler_errors", http_handler_errors, []},
+ {"/static_attribute_etag/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{etag, {attributes, [filepath, filesize, inode, mtime]}}]},
- {[<<"static_function_etag">>, '...'], cowboy_static,
+ {"/static_function_etag/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{etag, {fun static_function_etag/2, etag_data}}]},
- {[<<"static_specify_file">>, '...'], cowboy_static,
+ {"/static_specify_file/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{mimetypes, [{<<".css">>, [<<"text/css">>]}]},
{file, <<"test_file.css">>}]},
- {[<<"multipart">>], http_handler_multipart, []},
- {[<<"echo">>, <<"body">>], http_handler_echo_body, []},
- {[<<"bad_accept">>], rest_simple_resource, []},
- {[<<"simple">>], rest_simple_resource, []},
- {[<<"forbidden_post">>], rest_forbidden_resource, [true]},
- {[<<"simple_post">>], rest_forbidden_resource, [false]},
- {[<<"missing_get_callbacks">>], rest_missing_callbacks, []},
- {[<<"missing_put_callbacks">>], rest_missing_callbacks, []},
- {[<<"nodelete">>], rest_nodelete_resource, []},
- {[<<"resetags">>], rest_resource_etags, []},
- {[<<"rest_expires">>], rest_expires, []},
- {[<<"loop_timeout">>], http_handler_loop_timeout, []},
- {[], http_handler, []}
+ {"/multipart", http_handler_multipart, []},
+ {"/echo/body", http_handler_echo_body, []},
+ {"/bad_accept", rest_simple_resource, []},
+ {"/simple", rest_simple_resource, []},
+ {"/forbidden_post", rest_forbidden_resource, [true]},
+ {"/simple_post", rest_forbidden_resource, [false]},
+ {"/missing_get_callbacks", rest_missing_callbacks, []},
+ {"/missing_put_callbacks", rest_missing_callbacks, []},
+ {"/nodelete", rest_nodelete_resource, []},
+ {"/patch", rest_patch_resource, []},
+ {"/created_path", rest_created_path_resource, []},
+ {"/resetags", rest_resource_etags, []},
+ {"/rest_expires", rest_expires, []},
+ {"/loop_timeout", http_handler_loop_timeout, []},
+ {"/", http_handler, []}
]}
- ].
+ ]).
init_static_dir(Config) ->
Dir = filename:join(?config(priv_dir, Config), "static"),
@@ -408,10 +483,16 @@ check_status(Config) ->
{Ret, URL}
end || {Status, URL} <- Tests].
-%% @todo Convert to cowboy_client.
chunked_response(Config) ->
- {ok, {{"HTTP/1.1", 200, "OK"}, _, "chunked_handler\r\nworks fine!"}}
- = httpc:request(binary_to_list(build_url("/chunked_response", Config))).
+ Client = ?config(client, Config),
+ {ok, Client2} = cowboy_client:request(<<"GET">>,
+ build_url("/chunked_response", Config), Client),
+ {ok, 200, Headers, Client3} = cowboy_client:response(Client2),
+ true = lists:keymember(<<"transfer-encoding">>, 1, Headers),
+ {ok, Transport, Socket} = cowboy_client:transport(Client3),
+ {ok, <<"11\r\nchunked_handler\r\n\r\nB\r\nworks fine!\r\n0\r\n\r\n">>}
+ = Transport:recv(Socket, 44, 1000),
+ {error, closed} = cowboy_client:response(Client3).
%% Check if sending requests whose size is around the MTU breaks something.
echo_body(Config) ->
@@ -503,8 +584,8 @@ http10_hostless(Config) ->
ranch:start_listener(Name, 5,
?config(transport, Config), ?config(opts, Config) ++ [{port, Port10}],
cowboy_protocol, [
- {dispatch, [{'_', [
- {[<<"http1.0">>, <<"hostless">>], http_handler, []}]}]},
+ {env, [{dispatch, cowboy_router:compile([
+ {'_', [{"/http1.0/hostless", http_handler, []}]}])}]},
{max_keepalive, 50},
{timeout, 500}]
),
@@ -517,7 +598,8 @@ keepalive_max(Config) ->
URL = build_url("/", Config),
ok = keepalive_max_loop(Client, URL, 50).
-keepalive_max_loop(_, _, 0) ->
+keepalive_max_loop(Client, _, 0) ->
+ {error, closed} = cowboy_client:response(Client),
ok;
keepalive_max_loop(Client, URL, N) ->
Headers = [{<<"connection">>, <<"keep-alive">>}],
@@ -536,7 +618,8 @@ keepalive_nl(Config) ->
URL = build_url("/", Config),
ok = keepalive_nl_loop(Client, URL, 10).
-keepalive_nl_loop(_, _, 0) ->
+keepalive_nl_loop(Client, _, 0) ->
+ {error, closed} = cowboy_client:response(Client),
ok;
keepalive_nl_loop(Client, URL, N) ->
Headers = [{<<"connection">>, <<"keep-alive">>}],
@@ -619,6 +702,21 @@ onrequest_hook(Req) ->
Req3
end.
+onresponse_capitalize(Config) ->
+ Client = ?config(client, Config),
+ {ok, Client2} = cowboy_client:request(<<"GET">>,
+ build_url("/", Config), Client),
+ {ok, Transport, Socket} = cowboy_client:transport(Client2),
+ {ok, Data} = Transport:recv(Socket, 0, 1000),
+ false = nomatch =:= binary:match(Data, <<"Content-Length">>).
+
+%% Hook for the above onresponse_capitalize test.
+onresponse_capitalize_hook(Status, Headers, Body, Req) ->
+ Headers2 = [{cowboy_bstr:capitalize_token(N), V}
+ || {N, V} <- Headers],
+ {ok, Req2} = cowboy_req:reply(Status, Headers2, Body, Req),
+ Req2.
+
onresponse_crash(Config) ->
Client = ?config(client, Config),
{ok, Client2} = cowboy_client:request(<<"GET">>,
@@ -668,6 +766,18 @@ rest_bad_accept(Config) ->
Client),
{ok, 400, _, _} = cowboy_client:response(Client2).
+rest_created_path(Config) ->
+ Headers = [{<<"content-type">>, <<"text/plain">>}],
+ Body = <<"Whatever">>,
+ Client = ?config(client, Config),
+ URL = build_url("/created_path", Config),
+ {ok, Client2} = cowboy_client:request(<<"POST">>, URL, Headers,
+ Body, Client),
+ {ok, 303, ResHeaders, _} = cowboy_client:response(Client2),
+ {<<"location">>, _Location} =
+ lists:keyfind(<<"location">>, 1, ResHeaders),
+ ok.
+
rest_expires(Config) ->
Client = ?config(client, Config),
{ok, Client2} = cowboy_client:request(<<"GET">>,
@@ -742,6 +852,21 @@ rest_nodelete(Config) ->
build_url("/nodelete", Config), Client),
{ok, 500, _, _} = cowboy_client:response(Client2).
+rest_patch(Config) ->
+ Tests = [
+ {204, [{<<"content-type">>, <<"text/plain">>}], <<"whatever">>},
+ {422, [{<<"content-type">>, <<"text/plain">>}], <<"false">>},
+ {400, [{<<"content-type">>, <<"text/plain">>}], <<"halt">>},
+ {415, [{<<"content-type">>, <<"application/json">>}], <<"bad_content_type">>}
+ ],
+ Client = ?config(client, Config),
+ _ = [begin
+ {ok, Client2} = cowboy_client:request(<<"PATCH">>,
+ build_url("/patch", Config), Headers, Body, Client),
+ {ok, Status, _, _} = cowboy_client:response(Client2),
+ ok
+ end || {Status, Headers, Body} <- Tests].
+
rest_resource_get_etag(Config, Type) ->
rest_resource_get_etag(Config, Type, []).
@@ -806,6 +931,34 @@ set_resp_overwrite(Config) ->
{<<"server">>, <<"DesireDrive/1.0">>}
= lists:keyfind(<<"server">>, 1, Headers).
+slowloris(Config) ->
+ Client = ?config(client, Config),
+ Transport = ?config(transport, Config),
+ {ok, Client2} = cowboy_client:connect(
+ Transport, "localhost", ?config(port, Config), Client),
+ try
+ [begin
+ {ok, _} = cowboy_client:raw_request([C], Client2),
+ receive after 25 -> ok end
+ end || C <- "GET / HTTP/1.1\r\nHost: localhost\r\n"
+ "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US)\r\n"
+ "Cookie: name=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n\r\n"],
+ error(failure)
+ catch error:{badmatch, _} ->
+ ok
+ end.
+
+slowloris2(Config) ->
+ Client = ?config(client, Config),
+ Transport = ?config(transport, Config),
+ {ok, Client2} = cowboy_client:connect(
+ Transport, "localhost", ?config(port, Config), Client),
+ {ok, _} = cowboy_client:raw_request("GET / HTTP/1.1\r\n", Client2),
+ receive after 300 -> ok end,
+ {ok, _} = cowboy_client:raw_request("Host: localhost\r\n", Client2),
+ receive after 300 -> ok end,
+ {ok, 408, _, _} = cowboy_client:response(Client2).
+
static_attribute_etag(Config) ->
Client = ?config(client, Config),
{ok, Client2} = cowboy_client:request(<<"GET">>,
@@ -892,6 +1045,22 @@ stream_body_set_resp(Config) ->
{ok, <<"stream_body_set_resp">>, _}
= cowboy_client:response_body(Client3).
+stream_body_set_resp_close(Config) ->
+ Client = ?config(client, Config),
+ {ok, Client2} = cowboy_client:request(<<"GET">>,
+ build_url("/stream_body/set_resp_close", Config), Client),
+ {ok, 200, _, Client3} = cowboy_client:response(Client2),
+ {ok, Transport, Socket} = cowboy_client:transport(Client3),
+ case element(7, Client3) of
+ <<"stream_body_set_resp_close">> ->
+ ok;
+ Buffer ->
+ {ok, Rest} = Transport:recv(Socket, 26 - byte_size(Buffer), 1000),
+ <<"stream_body_set_resp_close">> = << Buffer/binary, Rest/binary >>,
+ ok
+ end,
+ {error, closed} = Transport:recv(Socket, 0, 1000).
+
te_chunked(Config) ->
Client = ?config(client, Config),
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
@@ -903,6 +1072,21 @@ te_chunked(Config) ->
{ok, 200, _, Client3} = cowboy_client:response(Client2),
{ok, Body, _} = cowboy_client:response_body(Client3).
+te_chunked_chopped(Config) ->
+ Client = ?config(client, Config),
+ Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
+ Body2 = iolist_to_binary(body_to_chunks(50, Body, [])),
+ {ok, Client2} = cowboy_client:request(<<"GET">>,
+ build_url("/echo/body", Config),
+ [{<<"transfer-encoding">>, <<"chunked">>}], Client),
+ {ok, Transport, Socket} = cowboy_client:transport(Client2),
+ _ = [begin
+ ok = Transport:send(Socket, << C >>),
+ ok = timer:sleep(10)
+ end || << C >> <= Body2],
+ {ok, 200, _, Client3} = cowboy_client:response(Client2),
+ {ok, Body, _} = cowboy_client:response_body(Client3).
+
te_chunked_delayed(Config) ->
Client = ?config(client, Config),
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
diff --git a/test/http_handler.erl b/test/http_handler.erl
index e569adb..e1f1665 100644
--- a/test/http_handler.erl
+++ b/test/http_handler.erl
@@ -2,7 +2,7 @@
-module(http_handler).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
-record(state, {headers, body}).
@@ -15,5 +15,5 @@ handle(Req, State=#state{headers=Headers, body=Body}) ->
{ok, Req2} = cowboy_req:reply(200, Headers, Body, Req),
{ok, Req2, State}.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/http_handler_echo_body.erl b/test/http_handler_echo_body.erl
index e4b1ee0..31595d5 100644
--- a/test/http_handler_echo_body.erl
+++ b/test/http_handler_echo_body.erl
@@ -2,18 +2,18 @@
-module(http_handler_echo_body).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_, http}, Req, _) ->
{ok, Req, undefined}.
handle(Req, State) ->
- {true, Req1} = cowboy_req:has_body(Req),
- {ok, Body, Req2} = cowboy_req:body(Req1),
+ true = cowboy_req:has_body(Req),
+ {ok, Body, Req2} = cowboy_req:body(Req),
{Size, Req3} = cowboy_req:body_length(Req2),
Size = byte_size(Body),
{ok, Req4} = cowboy_req:reply(200, [], Body, Req3),
{ok, Req4, State}.
-terminate(_, _) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/http_handler_errors.erl b/test/http_handler_errors.erl
index 30cbaeb..2d1066c 100644
--- a/test/http_handler_errors.erl
+++ b/test/http_handler_errors.erl
@@ -2,7 +2,7 @@
-module(http_handler_errors).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_Transport, http}, Req, _Opts) ->
{Case, Req1} = cowboy_req:qs_val(<<"case">>, Req),
@@ -36,5 +36,5 @@ handle(Req, <<"handle_after_reply">> = Case) ->
{ok, _Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
erlang:error(Case).
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/http_handler_init_shutdown.erl b/test/http_handler_init_shutdown.erl
index edea1a0..fd01983 100644
--- a/test/http_handler_init_shutdown.erl
+++ b/test/http_handler_init_shutdown.erl
@@ -2,7 +2,7 @@
-module(http_handler_init_shutdown).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_Transport, http}, Req, _Opts) ->
{ok, Req2} = cowboy_req:reply(<<"666 Init Shutdown Testing">>,
@@ -13,5 +13,5 @@ handle(Req, State) ->
{ok, Req2} = cowboy_req:reply(200, [], "Hello world!", Req),
{ok, Req2, State}.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/http_handler_long_polling.erl b/test/http_handler_long_polling.erl
index d61d697..763e1fe 100644
--- a/test/http_handler_long_polling.erl
+++ b/test/http_handler_long_polling.erl
@@ -2,7 +2,7 @@
-module(http_handler_long_polling).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, info/3, terminate/2]).
+-export([init/3, handle/2, info/3, terminate/3]).
init({_Transport, http}, Req, _Opts) ->
erlang:send_after(500, self(), timeout),
@@ -18,5 +18,5 @@ info(timeout, Req, State) ->
erlang:send_after(500, self(), timeout),
{loop, Req, State - 1, hibernate}.
-terminate(_Req, _State) ->
+terminate({normal, shutdown}, _, _) ->
ok.
diff --git a/test/http_handler_loop_timeout.erl b/test/http_handler_loop_timeout.erl
index c9bb15f..0155b1e 100644
--- a/test/http_handler_loop_timeout.erl
+++ b/test/http_handler_loop_timeout.erl
@@ -2,7 +2,7 @@
-module(http_handler_loop_timeout).
-behaviour(cowboy_loop_handler).
--export([init/3, info/3, terminate/2]).
+-export([init/3, info/3, terminate/3]).
init({_, http}, Req, _) ->
erlang:send_after(1000, self(), error_timeout),
@@ -12,5 +12,5 @@ info(error_timeout, Req, State) ->
{ok, Req2} = cowboy_req:reply(500, Req),
{ok, Req2, State}.
-terminate(_, _) ->
+terminate({normal, timeout}, _, _) ->
ok.
diff --git a/test/http_handler_multipart.erl b/test/http_handler_multipart.erl
index 850574f..8209535 100644
--- a/test/http_handler_multipart.erl
+++ b/test/http_handler_multipart.erl
@@ -2,7 +2,7 @@
-module(http_handler_multipart).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_Transport, http}, Req, []) ->
{ok, Req, {}}.
@@ -12,7 +12,7 @@ handle(Req, State) ->
{ok, Req3} = cowboy_req:reply(200, [], term_to_binary(Result), Req2),
{ok, Req3, State}.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
acc_multipart(Req) ->
diff --git a/test/http_handler_set_resp.erl b/test/http_handler_set_resp.erl
index 70ddf79..d00d72a 100644
--- a/test/http_handler_set_resp.erl
+++ b/test/http_handler_set_resp.erl
@@ -2,7 +2,7 @@
-module(http_handler_set_resp).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
init({_Transport, http}, Req, Opts) ->
Headers = proplists:get_value(headers, Opts, []),
@@ -27,5 +27,5 @@ handle(Req, State) ->
end
end.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/http_handler_stream_body.erl b/test/http_handler_stream_body.erl
index feb4f78..5e42fa7 100644
--- a/test/http_handler_stream_body.erl
+++ b/test/http_handler_stream_body.erl
@@ -2,7 +2,7 @@
-module(http_handler_stream_body).
-behaviour(cowboy_http_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3, handle/2, terminate/3]).
-record(state, {headers, body, reply}).
@@ -12,13 +12,17 @@ init({_Transport, http}, Req, Opts) ->
Reply = proplists:get_value(reply, Opts),
{ok, Req, #state{headers=Headers, body=Body, reply=Reply}}.
-handle(Req, State=#state{headers=_Headers, body=Body, reply=set_resp}) ->
- {ok, Transport, Socket} = cowboy_req:transport(Req),
- SFun = fun() -> Transport:send(Socket, Body), sent end,
- SLen = iolist_size(Body),
- Req2 = cowboy_req:set_resp_body_fun(SLen, SFun, Req),
+handle(Req, State=#state{headers=_Headers, body=Body, reply=Reply}) ->
+ SFun = fun(Socket, Transport) -> Transport:send(Socket, Body) end,
+ Req2 = case Reply of
+ set_resp ->
+ SLen = iolist_size(Body),
+ cowboy_req:set_resp_body_fun(SLen, SFun, Req);
+ set_resp_close ->
+ cowboy_req:set_resp_body_fun(SFun, Req)
+ end,
{ok, Req3} = cowboy_req:reply(200, Req2),
{ok, Req3, State}.
-terminate(_Req, _State) ->
+terminate(_, _, _) ->
ok.
diff --git a/test/rest_created_path_resource.erl b/test/rest_created_path_resource.erl
new file mode 100644
index 0000000..5ad8cfc
--- /dev/null
+++ b/test/rest_created_path_resource.erl
@@ -0,0 +1,35 @@
+-module(rest_created_path_resource).
+-export([init/3]).
+-export([allowed_methods/2]).
+-export([content_types_provided/2]).
+-export([get_text_plain/2]).
+-export([post_is_create/2]).
+-export([content_types_accepted/2]).
+-export([post_text_plain/2]).
+-export([created_path/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+{[<<"HEAD">>, <<"GET">>, <<"POST">>], Req, State}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
+post_is_create(Req, State) ->
+ {true, Req, State}.
+
+content_types_accepted(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, post_text_plain}], Req, State}.
+
+post_text_plain(Req, State) ->
+ {true, Req, State}.
+
+created_path(Req, State) ->
+ {<<"/created">>, Req, State}.
+
+
diff --git a/test/rest_patch_resource.erl b/test/rest_patch_resource.erl
new file mode 100644
index 0000000..e265f6f
--- /dev/null
+++ b/test/rest_patch_resource.erl
@@ -0,0 +1,34 @@
+-module(rest_patch_resource).
+-export([init/3, allowed_methods/2, content_types_provided/2, get_text_plain/2,
+ content_types_accepted/2, patch_text_plain/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+ {[<<"HEAD">>, <<"GET">>, <<"PATCH">>], Req, State}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
+content_types_accepted(Req, State) ->
+ case cowboy_req:method(Req) of
+ {<<"PATCH">>, Req0} ->
+ {[{{<<"text">>, <<"plain">>, []}, patch_text_plain}], Req0, State};
+ {_, Req0} ->
+ {[], Req0, State}
+ end.
+
+patch_text_plain(Req, State) ->
+ case cowboy_req:body(Req) of
+ {ok, <<"halt">>, Req0} ->
+ {ok, Req1} = cowboy_req:reply(400, Req0),
+ {halt, Req1, State};
+ {ok, <<"false">>, Req0} ->
+ {false, Req0, State};
+ {ok, _Body, Req0} ->
+ {true, Req0, State}
+ end.
diff --git a/test/websocket_echo_handler.erl b/test/websocket_echo_handler.erl
index 926b51d..21b0116 100644
--- a/test/websocket_echo_handler.erl
+++ b/test/websocket_echo_handler.erl
@@ -1,21 +1,14 @@
%% Feel free to use, reuse and abuse the code in this file.
-module(websocket_echo_handler).
--behaviour(cowboy_http_handler).
-behaviour(cowboy_websocket_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3]).
-export([websocket_init/3, websocket_handle/3,
websocket_info/3, websocket_terminate/3]).
init(_Any, _Req, _Opts) ->
{upgrade, protocol, cowboy_websocket}.
-handle(_Req, _State) ->
- exit(badarg).
-
-terminate(_Req, _State) ->
- exit(badarg).
-
websocket_init(_TransportName, Req, _Opts) ->
Req2 = cowboy_req:compact(Req),
{ok, Req2, undefined}.
diff --git a/test/websocket_handler.erl b/test/websocket_handler.erl
index caf4828..a9863ae 100644
--- a/test/websocket_handler.erl
+++ b/test/websocket_handler.erl
@@ -1,21 +1,14 @@
%% Feel free to use, reuse and abuse the code in this file.
-module(websocket_handler).
--behaviour(cowboy_http_handler).
-behaviour(cowboy_websocket_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3]).
-export([websocket_init/3, websocket_handle/3,
websocket_info/3, websocket_terminate/3]).
init(_Any, _Req, _Opts) ->
{upgrade, protocol, cowboy_websocket}.
-handle(_Req, _State) ->
- exit(badarg).
-
-terminate(_Req, _State) ->
- exit(badarg).
-
websocket_init(_TransportName, Req, _Opts) ->
erlang:start_timer(1000, self(), <<"websocket_init">>),
Req2 = cowboy_req:compact(Req),
diff --git a/test/websocket_handler_init_shutdown.erl b/test/websocket_handler_init_shutdown.erl
index 5fdfba3..7ccea05 100644
--- a/test/websocket_handler_init_shutdown.erl
+++ b/test/websocket_handler_init_shutdown.erl
@@ -1,21 +1,14 @@
%% Feel free to use, reuse and abuse the code in this file.
-module(websocket_handler_init_shutdown).
--behaviour(cowboy_http_handler).
-behaviour(cowboy_websocket_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3]).
-export([websocket_init/3, websocket_handle/3,
websocket_info/3, websocket_terminate/3]).
init(_Any, _Req, _Opts) ->
{upgrade, protocol, cowboy_websocket}.
-handle(_Req, _State) ->
- exit(badarg).
-
-terminate(_Req, _State) ->
- exit(badarg).
-
websocket_init(_TransportName, Req, _Opts) ->
{ok, Req2} = cowboy_req:reply(403, Req),
{shutdown, Req2}.
diff --git a/test/ws_SUITE.erl b/test/ws_SUITE.erl
index 34befda..06d4b3e 100644
--- a/test/ws_SUITE.erl
+++ b/test/ws_SUITE.erl
@@ -1,4 +1,4 @@
-%% Copyright (c) 2011, Loïc Hoguin <[email protected]>
+%% Copyright (c) 2011-2013, 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
@@ -63,7 +63,6 @@ groups() ->
[{ws, [], BaseTests}].
init_per_suite(Config) ->
- application:start(inets),
application:start(crypto),
application:start(ranch),
application:start(cowboy),
@@ -73,13 +72,12 @@ end_per_suite(_Config) ->
application:stop(cowboy),
application:stop(ranch),
application:stop(crypto),
- application:stop(inets),
ok.
init_per_group(ws, Config) ->
Port = 33080,
cowboy:start_http(ws, 100, [{port, Port}], [
- {dispatch, init_dispatch()}
+ {env, [{dispatch, init_dispatch()}]}
]),
[{port, Port}|Config].
@@ -90,42 +88,39 @@ end_per_group(Listener, _Config) ->
%% Dispatch configuration.
init_dispatch() ->
- [
- {[<<"localhost">>], [
- {[<<"websocket">>], websocket_handler, []},
- {[<<"ws_echo_handler">>], websocket_echo_handler, []},
- {[<<"ws_init_shutdown">>], websocket_handler_init_shutdown, []},
- {[<<"ws_send_many">>], ws_send_many_handler, [
+ cowboy_router:compile([
+ {"localhost", [
+ {"/websocket", websocket_handler, []},
+ {"/ws_echo_handler", websocket_echo_handler, []},
+ {"/ws_init_shutdown", websocket_handler_init_shutdown, []},
+ {"/ws_send_many", ws_send_many_handler, [
{sequence, [
{text, <<"one">>},
{text, <<"two">>},
{text, <<"seven!">>}]}
]},
- {[<<"ws_send_close">>], ws_send_many_handler, [
+ {"/ws_send_close", ws_send_many_handler, [
{sequence, [
{text, <<"send">>},
close,
{text, <<"won't be received">>}]}
]},
- {[<<"ws_send_close_payload">>], ws_send_many_handler, [
+ {"/ws_send_close_payload", ws_send_many_handler, [
{sequence, [
{text, <<"send">>},
{close, 1001, <<"some text!">>},
{text, <<"won't be received">>}]}
]},
- {[<<"ws_timeout_hibernate">>], ws_timeout_hibernate_handler, []},
- {[<<"ws_timeout_cancel">>], ws_timeout_cancel_handler, []},
- {[<<"ws_upgrade_with_opts">>], ws_upgrade_with_opts_handler,
+ {"/ws_timeout_hibernate", ws_timeout_hibernate_handler, []},
+ {"/ws_timeout_cancel", ws_timeout_cancel_handler, []},
+ {"/ws_upgrade_with_opts", ws_upgrade_with_opts_handler,
<<"failure">>}
]}
- ].
+ ]).
%% ws and wss.
-%% This test makes sure the code works even if we wait for a reply
-%% before sending the third challenge key in the GET body.
-%%
-%% This ensures that Cowboy will work fine with proxies on hixie.
+%% We do not support hixie76 anymore.
ws0(Config) ->
{port, Port} = lists:keyfind(port, 1, Config),
{ok, Socket} = gen_tcp:connect("localhost", Port,
@@ -140,34 +135,8 @@ ws0(Config) ->
"Sec-Websocket-Key2: 1711 M;4\\74 80<6\r\n"
"\r\n"),
{ok, Handshake} = gen_tcp:recv(Socket, 0, 6000),
- {ok, {http_response, {1, 1}, 101, "WebSocket Protocol Handshake"}, Rest}
- = erlang:decode_packet(http, Handshake, []),
- [Headers, <<>>] = websocket_headers(
- erlang:decode_packet(httph, Rest, []), []),
- {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers),
- {'Upgrade', "WebSocket"} = lists:keyfind('Upgrade', 1, Headers),
- {"sec-websocket-location", "ws://localhost/websocket"}
- = lists:keyfind("sec-websocket-location", 1, Headers),
- {"sec-websocket-origin", "http://localhost"}
- = lists:keyfind("sec-websocket-origin", 1, Headers),
- ok = gen_tcp:send(Socket, <<15,245,8,18,2,204,133,33>>),
- {ok, Body} = gen_tcp:recv(Socket, 0, 6000),
- <<169,244,191,103,146,33,149,59,74,104,67,5,99,118,171,236>> = Body,
- ok = gen_tcp:send(Socket, << 0, "client_msg", 255 >>),
- {ok, << 0, "client_msg", 255 >>} = gen_tcp:recv(Socket, 0, 6000),
- {ok, << 0, "websocket_init", 255 >>} = gen_tcp:recv(Socket, 0, 6000),
- {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000),
- {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000),
- {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000),
- %% We try to send another HTTP request to make sure
- %% the server closed the request.
- ok = gen_tcp:send(Socket, [
- << 255, 0 >>, %% Close websocket command.
- "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n" %% Server should ignore it.
- ]),
- {ok, << 255, 0 >>} = gen_tcp:recv(Socket, 0, 6000),
- {error, closed} = gen_tcp:recv(Socket, 0, 6000),
- ok.
+ {ok, {http_response, {1, 1}, 400, _}, _}
+ = erlang:decode_packet(http, Handshake, []).
ws8(Config) ->
{port, Port} = lists:keyfind(port, 1, Config),
@@ -203,9 +172,9 @@ ws8(Config) ->
= gen_tcp:recv(Socket, 0, 6000),
{ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>}
= gen_tcp:recv(Socket, 0, 6000),
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 1:1, 0:7, 0:32 >>), %% ping
{ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -254,7 +223,7 @@ ws8_single_bytes(Config) ->
ok = gen_tcp:send(Socket, << 16#81 >>), %% send one byte
ok = timer:sleep(100), %% sleep for a period
ok = gen_tcp:send(Socket, << 16#85 >>), %% send another and so on
- ok = timer:sleep(100),
+ ok = timer:sleep(100),
ok = gen_tcp:send(Socket, << 16#37 >>),
ok = timer:sleep(100),
ok = gen_tcp:send(Socket, << 16#fa >>),
@@ -282,9 +251,9 @@ ws8_single_bytes(Config) ->
= gen_tcp:recv(Socket, 0, 6000),
{ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>}
= gen_tcp:recv(Socket, 0, 6000),
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 1:1, 0:7, 0:32 >>), %% ping
{ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -317,7 +286,7 @@ ws13(Config) ->
{ok, << 1:1, 0:3, 1:4, 0:1, 5:7, "Hello" >>}
= gen_tcp:recv(Socket, 0, 6000),
%% binary (empty)
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 2:4, 0:8 >>),
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 2:4, 1:1, 0:7, 0:32 >>),
{ok, << 1:1, 0:3, 2:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
%% binary
ok = gen_tcp:send(Socket, << 16#82, 16#85, 16#37, 16#fa, 16#21, 16#3d,
@@ -333,9 +302,9 @@ ws13(Config) ->
= gen_tcp:recv(Socket, 0, 6000),
{ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>}
= gen_tcp:recv(Socket, 0, 6000),
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 1:1, 0:7, 0:32 >>), %% ping
{ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -425,7 +394,7 @@ ws_send_many(Config) ->
<< 1:1, 0:3, 1:4, 0:1, 3:7, "one",
1:1, 0:3, 1:4, 0:1, 3:7, "two",
1:1, 0:3, 1:4, 0:1, 6:7, "seven!" >> = Many,
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -479,8 +448,7 @@ ws_text_fragments(Config) ->
<< 16#9f >>, << 16#4d >>, << 16#51 >>, << 16#58 >>]),
{ok, << 1:1, 0:3, 1:4, 0:1, 15:7, "HelloHelloHello" >>}
= gen_tcp:recv(Socket, 0, 6000),
-
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -507,7 +475,7 @@ ws_timeout_hibernate(Config) ->
{'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers),
{"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}
= lists:keyfind("sec-websocket-accept", 1, Headers),
- {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
+ {ok, << 1:1, 0:3, 8:4, 0:1, 2:7, 1000:16 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -534,7 +502,7 @@ ws_timeout_cancel(Config) ->
{'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers),
{"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}
= lists:keyfind("sec-websocket-accept", 1, Headers),
- {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
+ {ok, << 1:1, 0:3, 8:4, 0:1, 2:7, 1000:16 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -547,41 +515,28 @@ ws_timeout_reset(Config) ->
"GET /ws_timeout_cancel HTTP/1.1\r\n"
"Host: localhost\r\n"
"Connection: Upgrade\r\n"
- "Upgrade: WebSocket\r\n"
- "Origin: http://localhost\r\n"
- "Sec-Websocket-Key1: Y\" 4 1Lj!957b8@0H756!i\r\n"
- "Sec-Websocket-Key2: 1711 M;4\\74 80<6\r\n"
+ "Upgrade: websocket\r\n"
+ "Sec-WebSocket-Origin: http://localhost\r\n"
+ "Sec-Websocket-Version: 13\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"\r\n"]),
{ok, Handshake} = gen_tcp:recv(Socket, 0, 6000),
- {ok, {http_response, {1, 1}, 101, "WebSocket Protocol Handshake"}, Rest}
+ {ok, {http_response, {1, 1}, 101, "Switching Protocols"}, Rest}
= erlang:decode_packet(http, Handshake, []),
[Headers, <<>>] = websocket_headers(
erlang:decode_packet(httph, Rest, []), []),
{'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers),
- {'Upgrade', "WebSocket"} = lists:keyfind('Upgrade', 1, Headers),
- {"sec-websocket-location", "ws://localhost/ws_timeout_cancel"}
- = lists:keyfind("sec-websocket-location", 1, Headers),
- {"sec-websocket-origin", "http://localhost"}
- = lists:keyfind("sec-websocket-origin", 1, Headers),
- ok = gen_tcp:send(Socket, <<15,245,8,18,2,204,133,33>>),
- {ok, Body} = gen_tcp:recv(Socket, 0, 6000),
- <<169,244,191,103,146,33,149,59,74,104,67,5,99,118,171,236>> = Body,
- ok = gen_tcp:send(Socket, << 0, "msg sent", 255 >>),
- {ok, << 0, "msg sent", 255 >>}
- = gen_tcp:recv(Socket, 0, 6000),
- ok = timer:sleep(500),
- ok = gen_tcp:send(Socket, << 0, "msg sent", 255 >>),
- {ok, << 0, "msg sent", 255 >>}
- = gen_tcp:recv(Socket, 0, 6000),
- ok = timer:sleep(500),
- ok = gen_tcp:send(Socket, << 0, "msg sent", 255 >>),
- {ok, << 0, "msg sent", 255 >>}
- = gen_tcp:recv(Socket, 0, 6000),
- ok = timer:sleep(500),
- ok = gen_tcp:send(Socket, << 0, "msg sent", 255 >>),
- {ok, << 0, "msg sent", 255 >>}
- = gen_tcp:recv(Socket, 0, 6000),
- {ok, << 255, 0 >>} = gen_tcp:recv(Socket, 0, 6000),
+ {'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers),
+ {"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}
+ = lists:keyfind("sec-websocket-accept", 1, Headers),
+ [begin
+ ok = gen_tcp:send(Socket, << 16#81, 16#85, 16#37, 16#fa, 16#21, 16#3d,
+ 16#7f, 16#9f, 16#4d, 16#51, 16#58 >>),
+ {ok, << 1:1, 0:3, 1:4, 0:1, 5:7, "Hello" >>}
+ = gen_tcp:recv(Socket, 0, 6000),
+ ok = timer:sleep(500)
+ end || _ <- [1, 2, 3, 4]],
+ {ok, << 1:1, 0:3, 8:4, 0:1, 2:7, 1000:16 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
@@ -609,7 +564,7 @@ ws_upgrade_with_opts(Config) ->
= lists:keyfind("sec-websocket-accept", 1, Headers),
{ok, Response} = gen_tcp:recv(Socket, 9, 6000),
<< 1:1, 0:3, 1:4, 0:1, 7:7, "success" >> = Response,
- ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close
+ ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 1:1, 0:7, 0:32 >>), %% close
{ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000),
{error, closed} = gen_tcp:recv(Socket, 0, 6000),
ok.
diff --git a/test/ws_timeout_cancel_handler.erl b/test/ws_timeout_cancel_handler.erl
index ee75d9b..68b0468 100644
--- a/test/ws_timeout_cancel_handler.erl
+++ b/test/ws_timeout_cancel_handler.erl
@@ -1,21 +1,14 @@
%% Feel free to use, reuse and abuse the code in this file.
-module(ws_timeout_cancel_handler).
--behaviour(cowboy_http_handler).
-behaviour(cowboy_websocket_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3]).
-export([websocket_init/3, websocket_handle/3,
websocket_info/3, websocket_terminate/3]).
init(_Any, _Req, _Opts) ->
{upgrade, protocol, cowboy_websocket}.
-handle(_Req, _State) ->
- exit(badarg).
-
-terminate(_Req, _State) ->
- exit(badarg).
-
websocket_init(_TransportName, Req, _Opts) ->
erlang:start_timer(500, self(), should_not_cancel_timer),
{ok, Req, undefined, 1000}.
diff --git a/test/ws_timeout_hibernate_handler.erl b/test/ws_timeout_hibernate_handler.erl
index ac6ee4f..41b9edd 100644
--- a/test/ws_timeout_hibernate_handler.erl
+++ b/test/ws_timeout_hibernate_handler.erl
@@ -1,21 +1,14 @@
%% Feel free to use, reuse and abuse the code in this file.
-module(ws_timeout_hibernate_handler).
--behaviour(cowboy_http_handler).
-behaviour(cowboy_websocket_handler).
--export([init/3, handle/2, terminate/2]).
+-export([init/3]).
-export([websocket_init/3, websocket_handle/3,
websocket_info/3, websocket_terminate/3]).
init(_Any, _Req, _Opts) ->
{upgrade, protocol, cowboy_websocket}.
-handle(_Req, _State) ->
- exit(badarg).
-
-terminate(_Req, _State) ->
- exit(badarg).
-
websocket_init(_TransportName, Req, _Opts) ->
{ok, Req, undefined, 1000, hibernate}.