Skip to content

Commit

Permalink
Merge pull request #6 from danielwhite/enhance-test-suite
Browse files Browse the repository at this point in the history
Enhance test suite
  • Loading branch information
danielwhite committed Nov 2, 2013
2 parents 04967ba + f5c10b4 commit 428293d
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 54 deletions.
137 changes: 97 additions & 40 deletions test/cors_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ groups() ->
preflight_method,
preflight_allowed_method,
preflight_credentials,
preflight_header,
preflight_allowed_header,
preflight_allowed_header_webkit
]}
Expand Down Expand Up @@ -90,17 +91,40 @@ end_per_group(Name, _) ->

%% Helpers

build_url(Path, Config) ->
build_url(Path, Options, Config) ->
Port = ?config(port, Config),
iolist_to_binary([<<"http://localhost:">>, integer_to_list(Port), Path]).
Params = build_params(Options),
iolist_to_binary([<<"http://localhost:">>, integer_to_list(Port), Path, Params]).

request(Method, Headers, Config) ->
build_params(Options) ->
case lists:map(fun build_param/1, Options) of
[] ->
[];
[["&" | First] | Rest] ->
["?", First, Rest]
end.

build_param({Name, Value}) ->
["&", atom_to_list(Name), "=", format_option(Value)].

format_option(Bin) when is_binary(Bin) ->
cowboy_http:urlencode(Bin);
format_option(Bool) when is_boolean(Bool) ->
io_lib:fwrite("~p", [Bool]);
format_option(List) when is_list(List) ->
IoList = lists:map(fun(X) -> [",", X] end, List),
<<",", Bin/binary>> = iolist_to_binary(IoList),
cowboy_http:urlencode(Bin).

request(Method, Headers, Options, Config) ->
{ok, Client} = cowboy_client:init([]),
{ok, Client2} = cowboy_client:request(Method, build_url(<<"/">>, Config), Headers, Client),
Url = build_url(<<"/">>, Options, Config),
ct:pal("Sending request to ~p", [Url]),
{ok, Client2} = cowboy_client:request(Method, Url, Headers, Client),
cowboy_client:response(Client2).

preflight(Headers, Config) ->
request(<<"OPTIONS">>, Headers, Config).
request(Method, Headers, Config) ->
request(Method, Headers, [], Config).

%% Tests

Expand All @@ -113,44 +137,57 @@ standard_no_origin_options(Config) ->
false = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers).

standard_get(Config) ->
Origin = <<"http://banned.example.com">>,
Origin = <<"http://example.com">>,
{ok, 204, Headers, _} = request(<<"GET">>, [{<<"Origin">>, Origin}], Config),
false = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers).

standard_options(Config) ->
Origin = <<"http://banned.example.com">>,
Origin = <<"http://example.com">>,
{ok, 204, Headers, _} = request(<<"OPTIONS">>, [{<<"Origin">>, Origin}], Config),
false = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers).

simple_allowed_get(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 204, Headers, _} =
request(<<"GET">>, [{<<"Origin">>, Origin}], Config),
request(<<"GET">>,
[{<<"Origin">>, Origin}],
[{allowed_origins, [<<"http://example.org">>, Origin]},
{allowed_methods, [<<"PUT">>, <<"GET">>]}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"x-exposed">>} = lists:keyfind(<<"access-control-expose-headers">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-credentials">>, 1, Headers).

simple_allowed_credentials_get(Config) ->
Origin = <<"http://credentials.example.com">>,
Origin = <<"http://example.com">>,
{ok, 204, Headers, _} =
request(<<"GET">>, [{<<"Origin">>, Origin}], Config),
request(<<"GET">>,
[{<<"Origin">>, Origin}],
[{allowed_origins, Origin},
{allow_credentials, true}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"x-exposed">>} = lists:keyfind(<<"access-control-expose-headers">>, 1, Headers),
{_, <<"true">>} = lists:keyfind(<<"access-control-allow-credentials">>, 1, Headers).

actual_options(Config) ->
%% OPTIONS request without Access-Control-Request-Method is not a pre-flight request.
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 204, Headers, _} =
preflight([{<<"Origin">>, Origin}], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin}],
[{allowed_origins, Origin}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
%% Ensure OPTIONS request was handled.
{_, <<"exposed">>} = lists:keyfind(<<"x-exposed">>, 1, Headers).

preflight_method(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([{<<"Origin">>, Origin}, {<<"Access-Control-Request-Method">>, <<"DELETE">>}], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"DELETE">>}],
[{allowed_origins, Origin}],
Config),
false = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-credentials">>, 1, Headers),
Expand All @@ -159,9 +196,14 @@ preflight_method(Config) ->
false = lists:keyfind(<<"x-exposed">>, 1, Headers).

preflight_allowed_method(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([{<<"Origin">>, Origin}, {<<"Access-Control-Request-Method">>, <<"PUT">>}], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>}],
[{allowed_origins, Origin},
{allowed_methods, [<<"GET">>, <<"PUT">>]}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"PUT">>} = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-credentials">>, 1, Headers),
Expand All @@ -170,9 +212,15 @@ preflight_allowed_method(Config) ->
false = lists:keyfind(<<"x-exposed">>, 1, Headers).

preflight_credentials(Config) ->
Origin = <<"http://credentials.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([{<<"Origin">>, Origin}, {<<"Access-Control-Request-Method">>, <<"PUT">>}], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>}],
[{allowed_origins, Origin},
{allowed_methods, <<"PUT">>},
{allow_credentials, true}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"PUT">>} = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
{_, <<"true">>} = lists:keyfind(<<"access-control-allow-credentials">>, 1, Headers),
Expand All @@ -181,13 +229,16 @@ preflight_credentials(Config) ->
false = lists:keyfind(<<"x-exposed">>, 1, Headers).

preflight_header(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([
{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"X-Custom">>}
], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"X-Custom">>}],
[{allowed_origins, Origin},
{allowed_methods, <<"PUT">>},
{allowed_headers, [<<"x-unused">>, <<"x-also-unused">>]}],
Config),
false = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
false = lists:keyfind(<<"access-control-allow-headers">>, 1, Headers),
Expand All @@ -197,13 +248,16 @@ preflight_header(Config) ->
false = lists:keyfind(<<"x-exposed">>, 1, Headers).

preflight_allowed_header(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([
{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"X-Requested">>}
], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"X-Requested">>}],
[{allowed_origins, Origin},
{allowed_methods, <<"PUT">>},
{allowed_headers, [<<"x-allowed">>, <<"x-requested">>]}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"PUT">>} = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
{_, <<"X-Requested">>} = lists:keyfind(<<"access-control-allow-headers">>, 1, Headers),
Expand All @@ -214,13 +268,16 @@ preflight_allowed_header(Config) ->

%% Test for Webkit browsers requesting 'Origin' header.
preflight_allowed_header_webkit(Config) ->
Origin = <<"http://allowed.example.com">>,
Origin = <<"http://example.com">>,
{ok, 200, Headers, _} =
preflight([
{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"origin, x-requested">>}
], Config),
request(<<"OPTIONS">>,
[{<<"Origin">>, Origin},
{<<"Access-Control-Request-Method">>, <<"PUT">>},
{<<"Access-Control-Request-Headers">>, <<"origin, x-requested">>}],
[{allowed_origins, Origin},
{allowed_methods, <<"PUT">>},
{allowed_headers, [<<"x-allowed">>, <<"x-requested">>]}],
Config),
{_, Origin} = lists:keyfind(<<"access-control-allow-origin">>, 1, Headers),
{_, <<"PUT">>} = lists:keyfind(<<"access-control-allow-methods">>, 1, Headers),
{_, <<"origin, x-requested">>} = lists:keyfind(<<"access-control-allow-headers">>, 1, Headers),
Expand Down
43 changes: 29 additions & 14 deletions test/cors_SUITE_data/cors_policy.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,40 @@ policy_init(Req) ->
{ok, Req, undefined_state}.

allowed_origins(Req, State) ->
Allowed = [
<<"http://allowed.example.com">>,
<<"http://credentials.example.com">>
],
{Allowed, Req, State}.
{Allowed, Req1} = parse_list(<<"allowed_origins">>, Req),
{Allowed, Req1, State}.

allow_credentials(Req, State) ->
case cowboy_req:header(<<"origin">>, Req) of
{<<"http://credentials.example.com">>, Req1} ->
{true, Req1, State};
{_, Req1} ->
{false, Req1, State}
end.
{IsAllowed, Req1} = parse_boolean(<<"allow_credentials">>, Req, false),
{IsAllowed, Req1, State}.

exposed_headers(Req, State) ->
{[<<"x-exposed">>], Req, State}.
{Exposed, Req1} = parse_list(<<"exposed_headers">>, Req),
{Exposed, Req1, State}.

allowed_headers(Req, State) ->
{[<<"x-requested">>], Req, State}.
{Allowed, Req1} = parse_list(<<"allowed_headers">>, Req),
{Allowed, Req1, State}.

allowed_methods(Req, State) ->
{[<<"GET">>, <<"POST">>, <<"PUT">>], Req, State}.
{Allowed, Req1} = parse_list(<<"allowed_methods">>, Req),
{Allowed, Req1, State}.

parse_list(Name, Req) ->
case cowboy_req:qs_val(Name, Req) of
{undefined, Req1} ->
{[], Req1};
{Bin, Req1} ->
List = binary:split(Bin, <<",">>, [global]),
{List, Req1}
end.

parse_boolean(Name, Req, Default) ->
case cowboy_req:qs_val(Name, Req) of
{undefined, Req1} ->
{Default, Req1};
{<<"true">>, Req1} ->
{true, Req1};
{<<"false">>, Req1} ->
{false, Req1}
end.

0 comments on commit 428293d

Please sign in to comment.