diff options
Diffstat (limited to 'test/handlers')
-rw-r--r-- | test/handlers/echo_h.erl | 46 | ||||
-rw-r--r-- | test/handlers/long_polling_h.erl | 1 | ||||
-rw-r--r-- | test/handlers/loop_handler_body_h.erl | 7 | ||||
-rw-r--r-- | test/handlers/multipart_h.erl | 65 | ||||
-rw-r--r-- | test/handlers/resp_h.erl | 151 |
5 files changed, 254 insertions, 16 deletions
diff --git a/test/handlers/echo_h.erl b/test/handlers/echo_h.erl index fd45c5f..fb7d8a8 100644 --- a/test/handlers/echo_h.erl +++ b/test/handlers/echo_h.erl @@ -12,10 +12,30 @@ init(Req, Opts) -> echo_arg(Arg, Req, Opts) end. -echo(<<"body">>, Req0, Opts) -> - {ok, Body, Req} = cowboy_req:read_body(Req0), - cowboy_req:reply(200, #{}, Body, Req), - {ok, Req, Opts}; +echo(<<"read_body">>, Req0, Opts) -> + case Opts of + #{crash := true} -> ct_helper:ignore(cowboy_req, read_body, 2); + _ -> ok + end, + {_, Body, Req} = case cowboy_req:path(Req0) of + <<"/full", _/bits>> -> read_body(Req0, <<>>); + <<"/opts", _/bits>> -> cowboy_req:read_body(Req0, Opts); + _ -> cowboy_req:read_body(Req0) + end, + {ok, cowboy_req:reply(200, #{}, Body, Req), Opts}; +echo(<<"read_urlencoded_body">>, Req0, Opts) -> + Path = cowboy_req:path(Req0), + case {Path, Opts} of + {<<"/opts", _/bits>>, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_body, 2); + {_, #{crash := true}} -> ct_helper:ignore(cowboy_req, read_urlencoded_body, 2); + _ -> ok + end, + {ok, Body, Req} = case Path of + <<"/opts", _/bits>> -> cowboy_req:read_urlencoded_body(Req0, Opts); + <<"/crash", _/bits>> -> cowboy_req:read_urlencoded_body(Req0, Opts); + _ -> cowboy_req:read_urlencoded_body(Req0) + end, + {ok, cowboy_req:reply(200, #{}, value_to_iodata(Body), Req), Opts}; echo(<<"uri">>, Req, Opts) -> Value = case cowboy_req:path_info(Req) of [<<"origin">>] -> cowboy_req:uri(Req, #{host => undefined}); @@ -25,8 +45,7 @@ echo(<<"uri">>, Req, Opts) -> [<<"set-port">>] -> cowboy_req:uri(Req, #{port => 123}); [] -> cowboy_req:uri(Req) end, - cowboy_req:reply(200, #{}, Value, Req), - {ok, Req, Opts}; + {ok, cowboy_req:reply(200, #{}, Value, Req), Opts}; echo(<<"match">>, Req, Opts) -> [Type|Fields0] = cowboy_req:path_info(Req), Fields = [binary_to_atom(F, latin1) || F <- Fields0], @@ -34,13 +53,11 @@ echo(<<"match">>, Req, Opts) -> <<"qs">> -> cowboy_req:match_qs(Fields, Req); <<"cookies">> -> cowboy_req:match_cookies(Fields, Req) end, - cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), - {ok, Req, Opts}; + {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts}; echo(What, Req, Opts) -> F = binary_to_atom(What, latin1), Value = cowboy_req:F(Req), - cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), - {ok, Req, Opts}. + {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts}. echo_arg(Arg0, Req, Opts) -> F = binary_to_atom(cowboy_req:binding(key, Req), latin1), @@ -52,8 +69,13 @@ echo_arg(Arg0, Req, Opts) -> undefined -> cowboy_req:F(Arg, Req); Default -> cowboy_req:F(Arg, Req, Default) end, - cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), - {ok, Req, Opts}. + {ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts}. + +read_body(Req0, Acc) -> + case cowboy_req:read_body(Req0) of + {ok, Data, Req} -> {ok, << Acc/binary, Data/binary >>, Req}; + {more, Data, Req} -> read_body(Req, << Acc/binary, Data/binary >>) + end. value_to_iodata(V) when is_integer(V) -> integer_to_binary(V); value_to_iodata(V) when is_atom(V) -> atom_to_binary(V, latin1); diff --git a/test/handlers/long_polling_h.erl b/test/handlers/long_polling_h.erl index 4f8e23f..17afa0a 100644 --- a/test/handlers/long_polling_h.erl +++ b/test/handlers/long_polling_h.erl @@ -14,6 +14,7 @@ init(Req, _) -> {cowboy_loop, Req, 2, 5000, hibernate}. info(timeout, Req, 0) -> + %% @todo Why 102? {stop, cowboy_req:reply(102, Req), 0}; info(timeout, Req, Count) -> erlang:send_after(200, self(), timeout), diff --git a/test/handlers/loop_handler_body_h.erl b/test/handlers/loop_handler_body_h.erl index 38ba2c0..e0ea41b 100644 --- a/test/handlers/loop_handler_body_h.erl +++ b/test/handlers/loop_handler_body_h.erl @@ -13,11 +13,10 @@ init(Req, _) -> self() ! timeout, {cowboy_loop, Req, undefined, 5000, hibernate}. -info(timeout, Req, State) -> - {ok, Body, Req2} = cowboy_req:read_body(Req), +info(timeout, Req0, State) -> + {ok, Body, Req} = cowboy_req:read_body(Req0), 100000 = byte_size(Body), - cowboy_req:reply(200, Req2), - {stop, Req, State}. + {stop, cowboy_req:reply(200, Req), State}. terminate(stop, _, _) -> ok. diff --git a/test/handlers/multipart_h.erl b/test/handlers/multipart_h.erl new file mode 100644 index 0000000..1b9297b --- /dev/null +++ b/test/handlers/multipart_h.erl @@ -0,0 +1,65 @@ +%% This module reads a multipart body and echoes it back as an Erlang term. + +-module(multipart_h). + +-export([init/2]). + +init(Req0, State) -> + {Result, Req} = case cowboy_req:binding(key, Req0) of + undefined -> acc_multipart(Req0, []); + <<"skip_body">> -> skip_body_multipart(Req0, []); + <<"read_part2">> -> read_part2_multipart(Req0, []); + <<"read_part_body2">> -> read_part_body2_multipart(Req0, []) + end, + {ok, cowboy_req:reply(200, #{}, term_to_binary(Result), Req), State}. + +acc_multipart(Req0, Acc) -> + case cowboy_req:read_part(Req0) of + {ok, Headers, Req1} -> + {ok, Body, Req} = stream_body(Req1, <<>>), + acc_multipart(Req, [{Headers, Body}|Acc]); + {done, Req} -> + {lists:reverse(Acc), Req} + end. + +stream_body(Req0, Acc) -> + case cowboy_req:read_part_body(Req0) of + {more, Data, Req} -> + stream_body(Req, << Acc/binary, Data/binary >>); + {ok, Data, Req} -> + {ok, << Acc/binary, Data/binary >>, Req} + end. + +skip_body_multipart(Req0, Acc) -> + case cowboy_req:read_part(Req0) of + {ok, Headers, Req} -> + skip_body_multipart(Req, [Headers|Acc]); + {done, Req} -> + {lists:reverse(Acc), Req} + end. + +read_part2_multipart(Req0, Acc) -> + case cowboy_req:read_part(Req0, #{length => 1, period => 1}) of + {ok, Headers, Req1} -> + {ok, Body, Req} = stream_body(Req1, <<>>), + acc_multipart(Req, [{Headers, Body}|Acc]); + {done, Req} -> + {lists:reverse(Acc), Req} + end. + +read_part_body2_multipart(Req0, Acc) -> + case cowboy_req:read_part(Req0) of + {ok, Headers, Req1} -> + {ok, Body, Req} = stream_body2(Req1, <<>>), + acc_multipart(Req, [{Headers, Body}|Acc]); + {done, Req} -> + {lists:reverse(Acc), Req} + end. + +stream_body2(Req0, Acc) -> + case cowboy_req:read_part_body(Req0, #{length => 1, period => 1}) of + {more, Data, Req} -> + stream_body(Req, << Acc/binary, Data/binary >>); + {ok, Data, Req} -> + {ok, << Acc/binary, Data/binary >>, Req} + end. diff --git a/test/handlers/resp_h.erl b/test/handlers/resp_h.erl new file mode 100644 index 0000000..bb64906 --- /dev/null +++ b/test/handlers/resp_h.erl @@ -0,0 +1,151 @@ +%% This module echoes back the value the test is interested in. + +-module(resp_h). + +-export([init/2]). + +init(Req, Opts) -> + do(cowboy_req:binding(key, Req), Req, Opts). + +do(<<"set_resp_cookie3">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + undefined -> + cowboy_req:set_resp_cookie(<<"mycookie">>, "myvalue", Req0); + <<"multiple">> -> + Req1 = cowboy_req:set_resp_cookie(<<"mycookie">>, "myvalue", Req0), + cowboy_req:set_resp_cookie(<<"yourcookie">>, <<"yourvalue">>, Req1); + <<"overwrite">> -> + Req1 = cowboy_req:set_resp_cookie(<<"mycookie">>, "myvalue", Req0), + cowboy_req:set_resp_cookie(<<"mycookie">>, <<"overwrite">>, Req1) + end, + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"set_resp_cookie4">>, Req0, Opts) -> + Req = cowboy_req:set_resp_cookie(<<"mycookie">>, "myvalue", #{path => cowboy_req:path(Req0)}, Req0), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"set_resp_header">>, Req0, Opts) -> + Req = cowboy_req:set_resp_header(<<"content-type">>, <<"text/plain">>, Req0), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"set_resp_body">>, Req0, Opts) -> + Arg = cowboy_req:binding(arg, Req0), + Req1 = case Arg of + <<"sendfile">> -> + AppFile = code:where_is_file("cowboy.app"), + cowboy_req:set_resp_body({sendfile, 0, filelib:file_size(AppFile), AppFile}, Req0); + _ -> + cowboy_req:set_resp_body(<<"OK">>, Req0) + end, + Req = case Arg of + <<"override">> -> + cowboy_req:reply(200, #{}, <<"OVERRIDE">>, Req1); + _ -> + cowboy_req:reply(200, Req1) + end, + {ok, Req, Opts}; +do(<<"has_resp_header">>, Req0, Opts) -> + false = cowboy_req:has_resp_header(<<"content-type">>, Req0), + Req = cowboy_req:set_resp_header(<<"content-type">>, <<"text/plain">>, Req0), + true = cowboy_req:has_resp_header(<<"content-type">>, Req), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"has_resp_body">>, Req0, Opts) -> + case cowboy_req:binding(arg, Req0) of + <<"sendfile">> -> + %% @todo Cases for sendfile. Note that sendfile 0 is unallowed. + false = cowboy_req:has_resp_body(Req0), + Req = cowboy_req:set_resp_body({sendfile, 0, 10, code:where_is_file("cowboy.app")}, Req0), + true = cowboy_req:has_resp_body(Req), + {ok, cowboy_req:reply(200, #{}, <<"OK">>, Req), Opts}; + undefined -> + false = cowboy_req:has_resp_body(Req0), + Req = cowboy_req:set_resp_body(<<"OK">>, Req0), + true = cowboy_req:has_resp_body(Req), + {ok, cowboy_req:reply(200, #{}, Req), Opts} + end; +do(<<"delete_resp_header">>, Req0, Opts) -> + false = cowboy_req:has_resp_header(<<"content-type">>, Req0), + Req1 = cowboy_req:set_resp_header(<<"content-type">>, <<"text/plain">>, Req0), + true = cowboy_req:has_resp_header(<<"content-type">>, Req1), + Req = cowboy_req:delete_resp_header(<<"content-type">>, Req1), + false = cowboy_req:has_resp_header(<<"content-type">>, Req), + {ok, cowboy_req:reply(200, #{}, "OK", Req), Opts}; +do(<<"reply2">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + <<"binary">> -> + cowboy_req:reply(<<"200 GOOD">>, Req0); + <<"error">> -> + ct_helper:ignore(cowboy_req, reply, 4), + cowboy_req:reply(ok, Req0); + <<"twice">> -> + ct_helper:ignore(cowboy_req, reply, 4), + Req1 = cowboy_req:reply(200, Req0), + cowboy_req:reply(200, Req1); + Status -> + cowboy_req:reply(binary_to_integer(Status), Req0) + end, + {ok, Req, Opts}; +do(<<"reply3">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + <<"error">> -> + ct_helper:ignore(cowboy_req, reply, 4), + cowboy_req:reply(200, ok, Req0); + Status -> + cowboy_req:reply(binary_to_integer(Status), + #{<<"content-type">> => <<"text/plain">>}, Req0) + end, + {ok, Req, Opts}; +do(<<"reply4">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + <<"error">> -> + ct_helper:ignore(erlang, iolist_size, 1), + cowboy_req:reply(200, #{}, ok, Req0); + Status -> + cowboy_req:reply(binary_to_integer(Status), #{}, <<"OK">>, Req0) + end, + {ok, Req, Opts}; +do(<<"stream_reply2">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + <<"binary">> -> + cowboy_req:stream_reply(<<"200 GOOD">>, Req0); + <<"error">> -> + ct_helper:ignore(cowboy_req, stream_reply, 3), + cowboy_req:stream_reply(ok, Req0); + Status -> + cowboy_req:stream_reply(binary_to_integer(Status), Req0) + end, + stream_body(Req), + {ok, Req, Opts}; +do(<<"stream_reply3">>, Req0, Opts) -> + Req = case cowboy_req:binding(arg, Req0) of + <<"error">> -> + ct_helper:ignore(cowboy_req, stream_reply, 3), + cowboy_req:stream_reply(200, ok, Req0); + Status -> + cowboy_req:stream_reply(binary_to_integer(Status), + #{<<"content-type">> => <<"text/plain">>}, Req0) + end, + stream_body(Req), + {ok, Req, Opts}; +do(<<"stream_body">>, Req, Opts) -> + %% Call stream_body without initiating streaming. + cowboy_req:stream_body(<<0:800000>>, fin, Req), + {ok, Req, Opts}; +do(<<"push">>, Req, Opts) -> + case cowboy_req:binding(arg, Req) of + <<"method">> -> + cowboy_req:push("/static/style.css", #{<<"accept">> => <<"text/css">>}, Req, + #{method => <<"HEAD">>}); + <<"origin">> -> + cowboy_req:push("/static/style.css", #{<<"accept">> => <<"text/css">>}, Req, + #{scheme => <<"ftp">>, host => <<"127.0.0.1">>, port => 21}); + <<"qs">> -> + cowboy_req:push("/static/style.css", #{<<"accept">> => <<"text/css">>}, Req, + #{qs => <<"server=cowboy&version=2.0">>}); + _ -> + cowboy_req:push("/static/style.css", #{<<"accept">> => <<"text/css">>}, Req), + %% The text/plain mime is not defined by default, so a 406 will be returned. + cowboy_req:push("/static/plain.txt", #{<<"accept">> => <<"text/plain">>}, Req) + end, + {ok, cowboy_req:reply(200, Req), Opts}. + +stream_body(Req) -> + _ = [cowboy_req:stream_body(<<0:800000>>, nofin, Req) || _ <- lists:seq(1,9)], + cowboy_req:stream_body(<<0:800000>>, fin, Req). |