aboutsummaryrefslogtreecommitdiffstats
path: root/test/handlers/echo_h.erl
blob: 1b672d100d9ff09d0affed60587acb1e31713036 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
%% This module echoes back the value the test is interested in.

-module(echo_h).

-export([init/2]).

init(Req, Opts) ->
	case cowboy_req:binding(arg, Req) of
		undefined ->
			echo(cowboy_req:binding(key, Req), Req, Opts);
		Arg ->
			echo_arg(Arg, Req, Opts)
	end.

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
		<<"/100-continue", _/bits>> ->
			cowboy_req:inform(100, Req0),
			cowboy_req:read_body(Req0);
		<<"/delay", _/bits>> ->
			timer:sleep(500),
			cowboy_req:read_body(Req0);
		<<"/full", _/bits>> -> read_body(Req0, <<>>);
		<<"/length", _/bits>> ->
			{_, _, Req1} = read_body(Req0, <<>>),
			Length = cowboy_req:body_length(Req1),
			{ok, integer_to_binary(Length), Req1};
		<<"/opts", _/bits>> -> cowboy_req:read_body(Req0, Opts);
		<<"/spawn", _/bits>> ->
			Parent = self(),
			Pid = spawn_link(fun() ->
				Parent ! {self(), cowboy_req:read_body(Req0)}
			end),
			receive
				{Pid, Msg} -> Msg
			after 5000 ->
				error(timeout)
			end;
		_ -> 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(<<"read_and_match_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_and_match_urlencoded_body([], Req0, Opts);
		<<"/crash", _/bits>> -> cowboy_req:read_and_match_urlencoded_body([], Req0, Opts);
		_ -> cowboy_req:read_and_match_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});
		[<<"protocol-relative">>] -> cowboy_req:uri(Req, #{scheme => undefined});
		[<<"no-qs">>] -> cowboy_req:uri(Req, #{qs => undefined});
		[<<"no-path">>] -> cowboy_req:uri(Req, #{path => undefined, qs => undefined});
		[<<"set-port">>] -> cowboy_req:uri(Req, #{port => 123});
		_ -> cowboy_req:uri(Req)
	end,
	{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],
	Value = case Type of
		<<"qs">> -> cowboy_req:match_qs(Fields, Req);
		<<"cookies">> -> cowboy_req:match_cookies(Fields, Req);
		<<"body_qs">> ->
			%% Note that the Req should not be discarded but for the
			%% purpose of this test this has no ill impacts.
			{ok, Match, _} = cowboy_req:read_and_match_urlencoded_body(Fields, Req),
			Match
	end,
	{ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts};
echo(<<"filter_then_parse_cookies">>, Req0, Opts) ->
	Req = cowboy_req:filter_cookies([cake, color], Req0),
	Value = cowboy_req:parse_cookies(Req),
	{ok, cowboy_req:reply(200, #{}, value_to_iodata(Value), Req), Opts};
echo(What, Req, Opts) ->
	Key = binary_to_atom(What, latin1),
	Value = case cowboy_req:path(Req) of
		<<"/direct/",_/bits>> -> maps:get(Key, Req);
		_ -> cowboy_req:Key(Req)
	end,
	{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),
	Arg = case F of
		binding -> binary_to_atom(Arg0, latin1);
		_ -> Arg0
	end,
	Value = case cowboy_req:binding(default, Req) of
		undefined -> cowboy_req:F(Arg, Req);
		Default -> cowboy_req:F(Arg, Req, Default)
	end,
	{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);
value_to_iodata(V) when is_list(V); is_tuple(V); is_map(V) -> io_lib:format("~999999p", [V]);
value_to_iodata(V) -> V.