aboutsummaryrefslogtreecommitdiffstats
path: root/test/http_SUITE_data
diff options
context:
space:
mode:
Diffstat (limited to 'test/http_SUITE_data')
-rw-r--r--test/http_SUITE_data/http_body_qs.erl39
-rw-r--r--test/http_SUITE_data/http_chunked.erl19
-rw-r--r--test/http_SUITE_data/http_echo_body.erl45
-rw-r--r--test/http_SUITE_data/http_errors.erl40
-rw-r--r--test/http_SUITE_data/http_handler.erl19
-rw-r--r--test/http_SUITE_data/http_init_shutdown.erl17
-rw-r--r--test/http_SUITE_data/http_long_polling.erl24
-rw-r--r--test/http_SUITE_data/http_loop_recv.erl18
-rw-r--r--test/http_SUITE_data/http_loop_timeout.erl16
-rw-r--r--test/http_SUITE_data/http_multipart.erl29
-rw-r--r--test/http_SUITE_data/http_set_resp.erl31
-rw-r--r--test/http_SUITE_data/http_stream_body.erl28
-rw-r--r--test/http_SUITE_data/rest_empty_resource.erl5
-rw-r--r--test/http_SUITE_data/rest_expires.erl22
-rw-r--r--test/http_SUITE_data/rest_forbidden_resource.erl31
-rw-r--r--test/http_SUITE_data/rest_missing_callbacks.erl21
-rw-r--r--test/http_SUITE_data/rest_nodelete_resource.erl17
-rw-r--r--test/http_SUITE_data/rest_param_all.erl36
-rw-r--r--test/http_SUITE_data/rest_patch_resource.erl34
-rw-r--r--test/http_SUITE_data/rest_resource_etags.erl30
-rw-r--r--test/http_SUITE_data/rest_simple_resource.erl12
21 files changed, 533 insertions, 0 deletions
diff --git a/test/http_SUITE_data/http_body_qs.erl b/test/http_SUITE_data/http_body_qs.erl
new file mode 100644
index 0000000..2280981
--- /dev/null
+++ b/test/http_SUITE_data/http_body_qs.erl
@@ -0,0 +1,39 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_body_qs).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_, http}, Req, _) ->
+ {ok, Req, undefined}.
+
+handle(Req, State) ->
+ {Method, Req2} = cowboy_req:method(Req),
+ HasBody = cowboy_req:has_body(Req2),
+ {ok, Req3} = maybe_echo(Method, HasBody, Req2),
+ {ok, Req3, State}.
+
+maybe_echo(<<"POST">>, true, Req) ->
+ case cowboy_req:body_qs(Req) of
+ {error,badlength} ->
+ echo(badlength, Req);
+ {ok, PostVals, Req2} ->
+ echo(proplists:get_value(<<"echo">>, PostVals), Req2)
+ end;
+
+maybe_echo(<<"POST">>, false, Req) ->
+ cowboy_req:reply(400, [], <<"Missing body.">>, Req);
+maybe_echo(_, _, Req) ->
+ %% Method not allowed.
+ cowboy_req:reply(405, Req).
+
+echo(badlength, Req) ->
+ cowboy_req:reply(413, [], <<"POST body bigger than 16000 bytes">>, Req);
+echo(undefined, Req) ->
+ cowboy_req:reply(400, [], <<"Missing echo parameter.">>, Req);
+echo(Echo, Req) ->
+ cowboy_req:reply(200,
+ [{<<"content-encoding">>, <<"utf-8">>}], Echo, Req).
+
+terminate(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_chunked.erl b/test/http_SUITE_data/http_chunked.erl
new file mode 100644
index 0000000..447c0f6
--- /dev/null
+++ b/test/http_SUITE_data/http_chunked.erl
@@ -0,0 +1,19 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_chunked).
+-behaviour(cowboy_http_handler).
+-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(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_echo_body.erl b/test/http_SUITE_data/http_echo_body.erl
new file mode 100644
index 0000000..014e05a
--- /dev/null
+++ b/test/http_SUITE_data/http_echo_body.erl
@@ -0,0 +1,45 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_echo_body).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_, http}, Req, _) ->
+ {ok, Req, undefined}.
+
+handle(Req, State) ->
+ true = cowboy_req:has_body(Req),
+ {ok, Req3} = case cowboy_req:body(1000000, Req) of
+ {error, chunked} -> handle_chunked(Req);
+ {error, badlength} -> handle_badlength(Req);
+ {ok, Body, Req2} -> handle_body(Req2, Body)
+ end,
+ {ok, Req3, State}.
+
+handle_chunked(Req) ->
+ {ok, Data, Req2} = read_body(Req, <<>>, 1000000),
+ {ok, Req3} = cowboy_req:reply(200, [], Data, Req2),
+ {ok, Req3}.
+
+handle_badlength(Req) ->
+ {ok, Req2} = cowboy_req:reply(413, [], <<"Request entity too large">>, Req),
+ {ok, Req2}.
+
+handle_body(Req, Body) ->
+ {Size, Req2} = cowboy_req:body_length(Req),
+ Size = byte_size(Body),
+ {ok, Req3} = cowboy_req:reply(200, [], Body, Req2),
+ {ok, Req3}.
+
+terminate(_, _, _) ->
+ ok.
+
+% Read chunked request content
+read_body(Req, Acc, BodyLengthRemaining) ->
+ case cowboy_req:stream_body(Req) of
+ {ok, Data, Req2} ->
+ BodyLengthRem = BodyLengthRemaining - byte_size(Data),
+ read_body(Req2, << Acc/binary, Data/binary >>, BodyLengthRem);
+ {done, Req2} ->
+ {ok, Acc, Req2}
+ end.
diff --git a/test/http_SUITE_data/http_errors.erl b/test/http_SUITE_data/http_errors.erl
new file mode 100644
index 0000000..8831362
--- /dev/null
+++ b/test/http_SUITE_data/http_errors.erl
@@ -0,0 +1,40 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_errors).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_Transport, http}, Req, _Opts) ->
+ {Case, Req1} = cowboy_req:qs_val(<<"case">>, Req),
+ case_init(Case, Req1).
+
+case_init(<<"init_before_reply">> = Case, _Req) ->
+ erlang:error(Case);
+
+case_init(<<"init_after_reply">> = Case, Req) ->
+ {ok, _Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
+ erlang:error(Case);
+
+case_init(<<"init_reply_handle_error">> = Case, Req) ->
+ {ok, Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
+ {ok, Req1, Case};
+
+case_init(<<"handle_before_reply">> = Case, Req) ->
+ {ok, Req, Case};
+
+case_init(<<"handle_after_reply">> = Case, Req) ->
+ {ok, Req, Case}.
+
+
+handle(_Req, <<"init_reply_handle_error">> = Case) ->
+ erlang:error(Case);
+
+handle(_Req, <<"handle_before_reply">> = Case) ->
+ erlang:error(Case);
+
+handle(Req, <<"handle_after_reply">> = Case) ->
+ {ok, _Req1} = cowboy_req:reply(200, [], "http_handler_crashes", Req),
+ erlang:error(Case).
+
+terminate(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_handler.erl b/test/http_SUITE_data/http_handler.erl
new file mode 100644
index 0000000..e1f1665
--- /dev/null
+++ b/test/http_SUITE_data/http_handler.erl
@@ -0,0 +1,19 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_handler).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+-record(state, {headers, body}).
+
+init({_Transport, http}, Req, Opts) ->
+ Headers = proplists:get_value(headers, Opts, []),
+ Body = proplists:get_value(body, Opts, "http_handler"),
+ {ok, Req, #state{headers=Headers, body=Body}}.
+
+handle(Req, State=#state{headers=Headers, body=Body}) ->
+ {ok, Req2} = cowboy_req:reply(200, Headers, Body, Req),
+ {ok, Req2, State}.
+
+terminate(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_init_shutdown.erl b/test/http_SUITE_data/http_init_shutdown.erl
new file mode 100644
index 0000000..1445569
--- /dev/null
+++ b/test/http_SUITE_data/http_init_shutdown.erl
@@ -0,0 +1,17 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_init_shutdown).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_Transport, http}, Req, _Opts) ->
+ {ok, Req2} = cowboy_req:reply(<<"666 Init Shutdown Testing">>,
+ [{<<"connection">>, <<"close">>}], Req),
+ {shutdown, Req2, undefined}.
+
+handle(Req, State) ->
+ {ok, Req2} = cowboy_req:reply(200, [], "Hello world!", Req),
+ {ok, Req2, State}.
+
+terminate(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_long_polling.erl b/test/http_SUITE_data/http_long_polling.erl
new file mode 100644
index 0000000..ad4e66e
--- /dev/null
+++ b/test/http_SUITE_data/http_long_polling.erl
@@ -0,0 +1,24 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_long_polling).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, info/3, terminate/3]).
+
+init({_Transport, http}, Req, _Opts) ->
+ erlang:send_after(500, self(), timeout),
+ {loop, Req, 5, 5000, hibernate}.
+
+handle(_Req, _State) ->
+ exit(badarg).
+
+info(timeout, Req, 0) ->
+ {ok, Req2} = cowboy_req:reply(102, Req),
+ {ok, Req2, 0};
+info(timeout, Req, State) ->
+ erlang:send_after(500, self(), timeout),
+ {loop, Req, State - 1, hibernate}.
+
+terminate({normal, shutdown}, _, _) ->
+ ok;
+terminate({error, overflow}, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_loop_recv.erl b/test/http_SUITE_data/http_loop_recv.erl
new file mode 100644
index 0000000..d0577f0
--- /dev/null
+++ b/test/http_SUITE_data/http_loop_recv.erl
@@ -0,0 +1,18 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_loop_recv).
+-behaviour(cowboy_loop_handler).
+-export([init/3, info/3, terminate/3]).
+
+init({_, http}, Req, _) ->
+ self() ! recv_timeout,
+ {loop, Req, undefined, 500, hibernate}.
+
+info(recv_timeout, Req, State) ->
+ {ok, Body, Req1} = cowboy_req:body(Req),
+ 100000 = byte_size(Body),
+ {ok, Req2} = cowboy_req:reply(200, Req1),
+ {ok, Req2, State}.
+
+terminate({normal, shutdown}, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_loop_timeout.erl b/test/http_SUITE_data/http_loop_timeout.erl
new file mode 100644
index 0000000..dd3472c
--- /dev/null
+++ b/test/http_SUITE_data/http_loop_timeout.erl
@@ -0,0 +1,16 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_loop_timeout).
+-behaviour(cowboy_loop_handler).
+-export([init/3, info/3, terminate/3]).
+
+init({_, http}, Req, _) ->
+ erlang:send_after(1000, self(), error_timeout),
+ {loop, Req, undefined, 500, hibernate}.
+
+info(error_timeout, Req, State) ->
+ {ok, Req2} = cowboy_req:reply(500, Req),
+ {ok, Req2, State}.
+
+terminate({normal, timeout}, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_multipart.erl b/test/http_SUITE_data/http_multipart.erl
new file mode 100644
index 0000000..c94739f
--- /dev/null
+++ b/test/http_SUITE_data/http_multipart.erl
@@ -0,0 +1,29 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_multipart).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_Transport, http}, Req, []) ->
+ {ok, Req, {}}.
+
+handle(Req, State) ->
+ {Result, Req2} = acc_multipart(Req),
+ {ok, Req3} = cowboy_req:reply(200, [], term_to_binary(Result), Req2),
+ {ok, Req3, State}.
+
+terminate(_, _, _) ->
+ ok.
+
+acc_multipart(Req) ->
+ acc_multipart(cowboy_req:multipart_data(Req), []).
+
+acc_multipart({headers, Headers, Req}, Acc) ->
+ acc_multipart(cowboy_req:multipart_data(Req), [{Headers, []}|Acc]);
+acc_multipart({body, Data, Req}, [{Headers, BodyAcc}|Acc]) ->
+ acc_multipart(cowboy_req:multipart_data(Req), [{Headers, [Data|BodyAcc]}|Acc]);
+acc_multipart({end_of_part, Req}, [{Headers, BodyAcc}|Acc]) ->
+ acc_multipart(cowboy_req:multipart_data(Req),
+ [{Headers, list_to_binary(lists:reverse(BodyAcc))}|Acc]);
+acc_multipart({eof, Req}, Acc) ->
+ {lists:reverse(Acc), Req}.
diff --git a/test/http_SUITE_data/http_set_resp.erl b/test/http_SUITE_data/http_set_resp.erl
new file mode 100644
index 0000000..821cc1d
--- /dev/null
+++ b/test/http_SUITE_data/http_set_resp.erl
@@ -0,0 +1,31 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_set_resp).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+init({_Transport, http}, Req, Opts) ->
+ Headers = proplists:get_value(headers, Opts, []),
+ Body = proplists:get_value(body, Opts, <<"http_handler_set_resp">>),
+ Req2 = lists:foldl(fun({Name, Value}, R) ->
+ cowboy_req:set_resp_header(Name, Value, R)
+ end, Req, Headers),
+ Req3 = cowboy_req:set_resp_body(Body, Req2),
+ Req4 = cowboy_req:set_resp_header(<<"x-cowboy-test">>, <<"ok">>, Req3),
+ Req5 = cowboy_req:set_resp_cookie(<<"cake">>, <<"lie">>, [], Req4),
+ {ok, Req5, undefined}.
+
+handle(Req, State) ->
+ case cowboy_req:has_resp_header(<<"x-cowboy-test">>, Req) of
+ false -> {ok, Req, State};
+ true ->
+ case cowboy_req:has_resp_body(Req) of
+ false -> {ok, Req, State};
+ true ->
+ {ok, Req2} = cowboy_req:reply(200, Req),
+ {ok, Req2, State}
+ end
+ end.
+
+terminate(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/http_stream_body.erl b/test/http_SUITE_data/http_stream_body.erl
new file mode 100644
index 0000000..4f45656
--- /dev/null
+++ b/test/http_SUITE_data/http_stream_body.erl
@@ -0,0 +1,28 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(http_stream_body).
+-behaviour(cowboy_http_handler).
+-export([init/3, handle/2, terminate/3]).
+
+-record(state, {headers, body, reply}).
+
+init({_Transport, http}, Req, Opts) ->
+ Headers = proplists:get_value(headers, Opts, []),
+ Body = proplists:get_value(body, Opts, "http_handler_stream_body"),
+ Reply = proplists:get_value(reply, Opts),
+ {ok, Req, #state{headers=Headers, body=Body, reply=Reply}}.
+
+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(_, _, _) ->
+ ok.
diff --git a/test/http_SUITE_data/rest_empty_resource.erl b/test/http_SUITE_data/rest_empty_resource.erl
new file mode 100644
index 0000000..7e7c00a
--- /dev/null
+++ b/test/http_SUITE_data/rest_empty_resource.erl
@@ -0,0 +1,5 @@
+-module(rest_empty_resource).
+-export([init/3]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
diff --git a/test/http_SUITE_data/rest_expires.erl b/test/http_SUITE_data/rest_expires.erl
new file mode 100644
index 0000000..4209041
--- /dev/null
+++ b/test/http_SUITE_data/rest_expires.erl
@@ -0,0 +1,22 @@
+-module(rest_expires).
+
+-export([init/3]).
+-export([content_types_provided/2]).
+-export([get_text_plain/2]).
+-export([expires/2]).
+-export([last_modified/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
+expires(Req, State) ->
+ {{{2012, 9, 21}, {22, 36, 14}}, Req, State}.
+
+last_modified(Req, State) ->
+ {{{2012, 9, 21}, {22, 36, 14}}, Req, State}.
diff --git a/test/http_SUITE_data/rest_forbidden_resource.erl b/test/http_SUITE_data/rest_forbidden_resource.erl
new file mode 100644
index 0000000..287ff62
--- /dev/null
+++ b/test/http_SUITE_data/rest_forbidden_resource.erl
@@ -0,0 +1,31 @@
+-module(rest_forbidden_resource).
+-export([init/3, rest_init/2, allowed_methods/2, forbidden/2,
+ content_types_provided/2, content_types_accepted/2,
+ to_text/2, from_text/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+rest_init(Req, [Forbidden]) ->
+ {ok, Req, Forbidden}.
+
+allowed_methods(Req, State) ->
+ {[<<"GET">>, <<"HEAD">>, <<"POST">>], Req, State}.
+
+forbidden(Req, State=true) ->
+ {true, Req, State};
+forbidden(Req, State=false) ->
+ {false, Req, State}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, to_text}], Req, State}.
+
+content_types_accepted(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, from_text}], Req, State}.
+
+to_text(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
+from_text(Req, State) ->
+ {Path, Req2} = cowboy_req:path(Req),
+ {Path, Req2, State}.
diff --git a/test/http_SUITE_data/rest_missing_callbacks.erl b/test/http_SUITE_data/rest_missing_callbacks.erl
new file mode 100644
index 0000000..171c856
--- /dev/null
+++ b/test/http_SUITE_data/rest_missing_callbacks.erl
@@ -0,0 +1,21 @@
+-module(rest_missing_callbacks).
+-export([init/3]).
+-export([allowed_methods/2]).
+-export([content_types_accepted/2]).
+-export([content_types_provided/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+ {[<<"GET">>, <<"PUT">>], Req, State}.
+
+content_types_accepted(Req, State) ->
+ {[
+ {<<"application/json">>, put_application_json}
+ ], Req, State}.
+
+content_types_provided(Req, State) ->
+ {[
+ {<<"text/plain">>, get_text_plain}
+ ], Req, State}.
diff --git a/test/http_SUITE_data/rest_nodelete_resource.erl b/test/http_SUITE_data/rest_nodelete_resource.erl
new file mode 100644
index 0000000..9f9670c
--- /dev/null
+++ b/test/http_SUITE_data/rest_nodelete_resource.erl
@@ -0,0 +1,17 @@
+-module(rest_nodelete_resource).
+-export([init/3, allowed_methods/2, content_types_provided/2,
+ get_text_plain/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+ {[<<"GET">>, <<"HEAD">>, <<"DELETE">>], Req, State}.
+
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
diff --git a/test/http_SUITE_data/rest_param_all.erl b/test/http_SUITE_data/rest_param_all.erl
new file mode 100644
index 0000000..09b8cd3
--- /dev/null
+++ b/test/http_SUITE_data/rest_param_all.erl
@@ -0,0 +1,36 @@
+-module(rest_param_all).
+
+-export([init/3]).
+-export([allowed_methods/2]).
+-export([content_types_provided/2]).
+-export([get_text_plain/2]).
+-export([content_types_accepted/2]).
+-export([put_text_plain/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+ {[<<"GET">>, <<"PUT">>], Req, State}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, '*'}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {{_, _, Param}, Req2} =
+ cowboy_req:meta(media_type, Req, {{<<"text">>, <<"plain">>}, []}),
+ Body = if
+ Param == '*' ->
+ <<"'*'">>;
+ Param == [] ->
+ <<"[]">>;
+ Param /= [] ->
+ iolist_to_binary([[Key, $=, Value] || {Key, Value} <- Param])
+ end,
+ {Body, Req2, State}.
+
+content_types_accepted(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, '*'}, put_text_plain}], Req, State}.
+
+put_text_plain(Req, State) ->
+ {true, Req, State}.
diff --git a/test/http_SUITE_data/rest_patch_resource.erl b/test/http_SUITE_data/rest_patch_resource.erl
new file mode 100644
index 0000000..e265f6f
--- /dev/null
+++ b/test/http_SUITE_data/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/http_SUITE_data/rest_resource_etags.erl b/test/http_SUITE_data/rest_resource_etags.erl
new file mode 100644
index 0000000..43f1e05
--- /dev/null
+++ b/test/http_SUITE_data/rest_resource_etags.erl
@@ -0,0 +1,30 @@
+-module(rest_resource_etags).
+-export([init/3, generate_etag/2, content_types_provided/2, get_text_plain/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+generate_etag(Req, State) ->
+ case cowboy_req:qs_val(<<"type">>, Req) of
+ %% Correct return values from generate_etag/2.
+ {<<"tuple-weak">>, Req2} ->
+ {{weak, <<"etag-header-value">>}, Req2, State};
+ {<<"tuple-strong">>, Req2} ->
+ {{strong, <<"etag-header-value">>}, Req2, State};
+ %% Backwards compatible return values from generate_etag/2.
+ {<<"binary-weak-quoted">>, Req2} ->
+ {<<"W/\"etag-header-value\"">>, Req2, State};
+ {<<"binary-strong-quoted">>, Req2} ->
+ {<<"\"etag-header-value\"">>, Req2, State};
+ %% Invalid return values from generate_etag/2.
+ {<<"binary-strong-unquoted">>, Req2} ->
+ {<<"etag-header-value">>, Req2, State};
+ {<<"binary-weak-unquoted">>, Req2} ->
+ {<<"W/etag-header-value">>, Req2, State}
+ end.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
diff --git a/test/http_SUITE_data/rest_simple_resource.erl b/test/http_SUITE_data/rest_simple_resource.erl
new file mode 100644
index 0000000..97145dd
--- /dev/null
+++ b/test/http_SUITE_data/rest_simple_resource.erl
@@ -0,0 +1,12 @@
+-module(rest_simple_resource).
+-export([init/3, content_types_provided/2, get_text_plain/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+