summaryrefslogtreecommitdiff
path: root/src/chttpd/test/eunit/chttpd_cors_test.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/chttpd/test/eunit/chttpd_cors_test.erl')
-rw-r--r--src/chttpd/test/eunit/chttpd_cors_test.erl582
1 files changed, 0 insertions, 582 deletions
diff --git a/src/chttpd/test/eunit/chttpd_cors_test.erl b/src/chttpd/test/eunit/chttpd_cors_test.erl
deleted file mode 100644
index 93b080fc6..000000000
--- a/src/chttpd/test/eunit/chttpd_cors_test.erl
+++ /dev/null
@@ -1,582 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(chttpd_cors_test).
-
--include_lib("couch/include/couch_db.hrl").
--include_lib("eunit/include/eunit.hrl").
--include_lib("chttpd/include/chttpd_cors.hrl").
-
--define(DEFAULT_ORIGIN, "http://example.com").
--define(DEFAULT_ORIGIN_HTTPS, "https://example.com").
--define(EXPOSED_HEADERS,
- "content-type, accept-ranges, etag, server, x-couch-request-id, " ++
- "x-couch-update-newrev, x-couchdb-body-time"
-).
-
--define(CUSTOM_SUPPORTED_METHODS, ?SUPPORTED_METHODS -- ["CONNECT"]).
--define(CUSTOM_SUPPORTED_HEADERS, ["extra" | ?SUPPORTED_HEADERS -- ["pragma"]]).
--define(CUSTOM_EXPOSED_HEADERS, ["expose" | ?COUCH_HEADERS]).
-
--define(CUSTOM_MAX_AGE, round(?CORS_DEFAULT_MAX_AGE / 2)).
-
-%% Test helpers
-
-empty_cors_config() ->
- [].
-
-minimal_cors_config() ->
- [
- {<<"enable_cors">>, true},
- {<<"origins">>, {[]}}
- ].
-
-simple_cors_config() ->
- [
- {<<"enable_cors">>, true},
- {<<"origins">>,
- {[
- {list_to_binary(?DEFAULT_ORIGIN), {[]}}
- ]}}
- ].
-
-wildcard_cors_config() ->
- [
- {<<"enable_cors">>, true},
- {<<"origins">>,
- {[
- {<<"*">>, {[]}}
- ]}}
- ].
-
-custom_cors_config() ->
- [
- {<<"enable_cors">>, true},
- {<<"allow_methods">>, ?CUSTOM_SUPPORTED_METHODS},
- {<<"allow_headers">>, ?CUSTOM_SUPPORTED_HEADERS},
- {<<"exposed_headers">>, ?CUSTOM_EXPOSED_HEADERS},
- {<<"max_age">>, ?CUSTOM_MAX_AGE},
- {<<"origins">>,
- {[
- {<<"*">>, {[]}}
- ]}}
- ].
-
-access_control_cors_config(AllowCredentials) ->
- [
- {<<"enable_cors">>, true},
- {<<"allow_credentials">>, AllowCredentials},
- {<<"origins">>,
- {[
- {list_to_binary(?DEFAULT_ORIGIN), {[]}}
- ]}}
- ].
-
-multiple_cors_config() ->
- [
- {<<"enable_cors">>, true},
- {<<"origins">>,
- {[
- {list_to_binary(?DEFAULT_ORIGIN), {[]}},
- {<<"https://example.com">>, {[]}},
- {<<"http://example.com:5984">>, {[]}},
- {<<"https://example.com:5984">>, {[]}}
- ]}}
- ].
-
-mock_request(Method, Path, Headers0) ->
- HeaderKey = "Access-Control-Request-Method",
- Headers =
- case proplists:get_value(HeaderKey, Headers0, undefined) of
- nil ->
- proplists:delete(HeaderKey, Headers0);
- undefined ->
- case Method of
- 'OPTIONS' ->
- [{HeaderKey, atom_to_list(Method)} | Headers0];
- _ ->
- Headers0
- end;
- _ ->
- Headers0
- end,
- Headers1 = mochiweb_headers:make(Headers),
- MochiReq = mochiweb_request:new(nil, Method, Path, {1, 1}, Headers1),
- PathParts = [
- list_to_binary(chttpd:unquote(Part))
- || Part <- string:tokens(Path, "/")
- ],
- #httpd{method = Method, mochi_req = MochiReq, path_parts = PathParts}.
-
-header(#httpd{} = Req, Key) ->
- chttpd:header_value(Req, Key);
-header({mochiweb_response, [_, _, Headers]}, Key) ->
- %% header(Headers, Key);
- mochiweb_headers:get_value(Key, Headers);
-header(Headers, Key) ->
- couch_util:get_value(Key, Headers, undefined).
-
-string_headers(H) ->
- string:join(H, ", ").
-
-assert_not_preflight_(Val) ->
- ?_assertEqual(not_preflight, Val).
-
-%% CORS disabled tests
-
-cors_disabled_test_() ->
- {"CORS disabled tests", [
- {"Empty user",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun empty_cors_config/0, [
- fun test_no_access_control_method_preflight_request_/1,
- fun test_no_headers_/1,
- fun test_no_headers_server_/1,
- fun test_no_headers_db_/1
- ]}}}
- ]}.
-
-%% CORS enabled tests
-
-cors_enabled_minimal_config_test_() ->
- {"Minimal CORS enabled, no Origins",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun minimal_cors_config/0, [
- fun test_no_access_control_method_preflight_request_/1,
- fun test_incorrect_origin_simple_request_/1,
- fun test_incorrect_origin_preflight_request_/1
- ]}}}.
-
-cors_enabled_simple_config_test_() ->
- {"Simple CORS config",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun simple_cors_config/0, [
- fun test_no_access_control_method_preflight_request_/1,
- fun test_preflight_request_/1,
- fun test_bad_headers_preflight_request_/1,
- fun test_good_headers_preflight_request_/1,
- fun test_db_request_/1,
- fun test_db_preflight_request_/1,
- fun test_db_host_origin_request_/1,
- fun test_preflight_with_port_no_origin_/1,
- fun test_preflight_with_scheme_no_origin_/1,
- fun test_preflight_with_scheme_port_no_origin_/1,
- fun test_case_sensitive_mismatch_of_allowed_origins_/1
- ]}}}.
-
-cors_enabled_custom_config_test_() ->
- {"Simple CORS config with custom allow_methods/allow_headers/exposed_headers",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun custom_cors_config/0, [
- fun test_good_headers_preflight_request_with_custom_config_/1,
- fun test_db_request_with_custom_config_/1
- ]}}}.
-
-cors_enabled_multiple_config_test_() ->
- {"Multiple options CORS config",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun multiple_cors_config/0, [
- fun test_no_access_control_method_preflight_request_/1,
- fun test_preflight_request_/1,
- fun test_db_request_/1,
- fun test_db_preflight_request_/1,
- fun test_db_host_origin_request_/1,
- fun test_preflight_with_port_with_origin_/1,
- fun test_preflight_with_scheme_with_origin_/1,
- fun test_preflight_with_scheme_port_with_origin_/1
- ]}}}.
-
-%% Access-Control-Allow-Credentials tests
-
-%% http://www.w3.org/TR/cors/#supports-credentials
-%% 6.1.3
-%% If the resource supports credentials add a single
-%% Access-Control-Allow-Origin header, with the value
-%% of the Origin header as value, and add a single
-%% Access-Control-Allow-Credentials header with the
-%% case-sensitive string "true" as value.
-%% Otherwise, add a single Access-Control-Allow-Origin
-%% header, with either the value of the Origin header
-%% or the string "*" as value.
-%% Note: The string "*" cannot be used for a resource
-%% that supports credentials.
-
-db_request_credentials_header_off_test_() ->
- {"Allow credentials disabled",
- {setup,
- fun() ->
- access_control_cors_config(false)
- end,
- fun test_db_request_credentials_header_off_/1}}.
-
-db_request_credentials_header_on_test_() ->
- {"Allow credentials enabled",
- {setup,
- fun() ->
- access_control_cors_config(true)
- end,
- fun test_db_request_credentials_header_on_/1}}.
-
-%% CORS wildcard tests
-
-cors_enabled_wildcard_test_() ->
- {"Wildcard CORS config",
- {setup, fun chttpd_test_util:start_couch/0, fun chttpd_test_util:stop_couch/1,
- {foreach, fun wildcard_cors_config/0, [
- fun test_no_access_control_method_preflight_request_/1,
- fun test_preflight_request_/1,
- fun test_preflight_request_no_allow_credentials_/1,
- fun test_preflight_request_empty_request_headers_/1,
- fun test_db_request_/1,
- fun test_db_preflight_request_/1,
- fun test_db_host_origin_request_/1,
- fun test_preflight_with_port_with_origin_/1,
- fun test_preflight_with_scheme_with_origin_/1,
- fun test_preflight_with_scheme_port_with_origin_/1,
- fun test_case_sensitive_mismatch_of_allowed_origins_/1
- ]}}}.
-
-%% Test generators
-
-test_no_headers_(OwnerConfig) ->
- Req = mock_request('GET', "/", []),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig)).
-
-test_no_headers_server_(OwnerConfig) ->
- Req = mock_request('GET', "/", [{"Origin", "http://127.0.0.1"}]),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig)).
-
-test_no_headers_db_(OwnerConfig) ->
- Headers = [{"Origin", "http://127.0.0.1"}],
- Req = mock_request('GET', "/my_db", Headers),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig)).
-
-test_incorrect_origin_simple_request_(OwnerConfig) ->
- Req = mock_request('GET', "/", [{"Origin", "http://127.0.0.1"}]),
- [
- ?_assert(chttpd_cors:is_cors_enabled(OwnerConfig)),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig))
- ].
-
-test_incorrect_origin_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", "http://127.0.0.1"},
- {"Access-Control-Request-Method", "GET"}
- ],
- Req = mock_request('GET', "/", Headers),
- [
- ?_assert(chttpd_cors:is_cors_enabled(OwnerConfig)),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig))
- ].
-
-test_bad_headers_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "GET"},
- {"Access-Control-Request-Headers", "X-Not-An-Allowed-Headers"}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- [
- ?_assert(chttpd_cors:is_cors_enabled(OwnerConfig)),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig))
- ].
-
-test_good_headers_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "GET"},
- {"Access-Control-Request-Headers", "accept-language"}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- ?assert(chttpd_cors:is_cors_enabled(OwnerConfig)),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(?SUPPORTED_METHODS),
- header(Headers1, "Access-Control-Allow-Methods")
- ),
- ?_assertEqual(
- string_headers(["accept-language"]),
- header(Headers1, "Access-Control-Allow-Headers")
- )
- ].
-
-test_good_headers_preflight_request_with_custom_config_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "GET"},
- {"Access-Control-Request-Headers", "accept-language, extra"},
- {"Access-Control-Max-Age", ?CORS_DEFAULT_MAX_AGE}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- ?assert(chttpd_cors:is_cors_enabled(OwnerConfig)),
- AllowMethods = couch_util:get_value(
- <<"allow_methods">>, OwnerConfig, ?SUPPORTED_METHODS
- ),
- MaxAge = couch_util:get_value(
- <<"max_age">>, OwnerConfig, ?CORS_DEFAULT_MAX_AGE
- ),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(AllowMethods),
- header(Headers1, "Access-Control-Allow-Methods")
- ),
- ?_assertEqual(
- string_headers(["accept-language", "extra"]),
- header(Headers1, "Access-Control-Allow-Headers")
- ),
- ?_assertEqual(
- MaxAge,
- header(Headers1, "Access-Control-Max-Age")
- )
- ].
-
-test_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "GET"}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(?SUPPORTED_METHODS),
- header(Headers1, "Access-Control-Allow-Methods")
- )
- ].
-
-test_no_access_control_method_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", notnil}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- assert_not_preflight_(chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig)).
-
-test_preflight_request_no_allow_credentials_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "GET"}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(?SUPPORTED_METHODS),
- header(Headers1, "Access-Control-Allow-Methods")
- ),
- ?_assertEqual(
- undefined,
- header(Headers1, "Access-Control-Allow-Credentials")
- )
- ].
-
-test_preflight_request_empty_request_headers_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN},
- {"Access-Control-Request-Method", "POST"},
- {"Access-Control-Request-Headers", ""}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(?SUPPORTED_METHODS),
- header(Headers1, "Access-Control-Allow-Methods")
- ),
- ?_assertEqual(
- "",
- header(Headers1, "Access-Control-Allow-Headers")
- )
- ].
-
-test_db_request_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN,
- Headers = [{"Origin", Origin}],
- Req = mock_request('GET', "/my_db", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- ?EXPOSED_HEADERS,
- header(Headers1, "Access-Control-Expose-Headers")
- )
- ].
-
-test_db_request_with_custom_config_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN,
- Headers = [{"Origin", Origin}, {"extra", "EXTRA"}],
- Req = mock_request('GET', "/my_db", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- ExposedHeaders = couch_util:get_value(
- <<"exposed_headers">>, OwnerConfig, ?COUCH_HEADERS
- ),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- lists:sort(["content-type" | ExposedHeaders]),
- lists:sort(
- split_list(header(Headers1, "Access-Control-Expose-Headers"))
- )
- )
- ].
-
-test_db_preflight_request_(OwnerConfig) ->
- Headers = [
- {"Origin", ?DEFAULT_ORIGIN}
- ],
- Req = mock_request('OPTIONS', "/my_db", Headers),
- {ok, Headers1} = chttpd_cors:maybe_handle_preflight_request(Req, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- string_headers(?SUPPORTED_METHODS),
- header(Headers1, "Access-Control-Allow-Methods")
- )
- ].
-
-test_db_host_origin_request_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN,
- Headers = [
- {"Origin", Origin},
- {"Host", "example.com"}
- ],
- Req = mock_request('GET', "/my_db", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- ?EXPOSED_HEADERS,
- header(Headers1, "Access-Control-Expose-Headers")
- )
- ].
-
-test_preflight_origin_helper_(OwnerConfig, Origin, ExpectedOrigin) ->
- Headers = [
- {"Origin", Origin},
- {"Access-Control-Request-Method", "GET"}
- ],
- Req = mock_request('OPTIONS', "/", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ExpectedOrigin,
- header(Headers1, "Access-Control-Allow-Origin")
- )
- ].
-
-test_preflight_with_port_no_origin_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN ++ ":5984",
- test_preflight_origin_helper_(OwnerConfig, Origin, undefined).
-
-test_preflight_with_port_with_origin_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN ++ ":5984",
- test_preflight_origin_helper_(OwnerConfig, Origin, Origin).
-
-test_preflight_with_scheme_no_origin_(OwnerConfig) ->
- test_preflight_origin_helper_(OwnerConfig, ?DEFAULT_ORIGIN_HTTPS, undefined).
-
-test_preflight_with_scheme_with_origin_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN_HTTPS,
- test_preflight_origin_helper_(OwnerConfig, Origin, Origin).
-
-test_preflight_with_scheme_port_no_origin_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN_HTTPS ++ ":5984",
- test_preflight_origin_helper_(OwnerConfig, Origin, undefined).
-
-test_preflight_with_scheme_port_with_origin_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN_HTTPS ++ ":5984",
- test_preflight_origin_helper_(OwnerConfig, Origin, Origin).
-
-test_case_sensitive_mismatch_of_allowed_origins_(OwnerConfig) ->
- Origin = "http://EXAMPLE.COM",
- Headers = [{"Origin", Origin}],
- Req = mock_request('GET', "/", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- ?EXPOSED_HEADERS,
- header(Headers1, "Access-Control-Expose-Headers")
- )
- ].
-
-test_db_request_credentials_header_off_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN,
- Headers = [{"Origin", Origin}],
- Req = mock_request('GET', "/", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- undefined,
- header(Headers1, "Access-Control-Allow-Credentials")
- )
- ].
-
-test_db_request_credentials_header_on_(OwnerConfig) ->
- Origin = ?DEFAULT_ORIGIN,
- Headers = [{"Origin", Origin}],
- Req = mock_request('GET', "/", Headers),
- Headers1 = chttpd_cors:headers(Req, Headers, Origin, OwnerConfig),
- [
- ?_assertEqual(
- ?DEFAULT_ORIGIN,
- header(Headers1, "Access-Control-Allow-Origin")
- ),
- ?_assertEqual(
- "true",
- header(Headers1, "Access-Control-Allow-Credentials")
- )
- ].
-
-split_list(S) ->
- re:split(S, "\\s*,\\s*", [trim, {return, list}]).