aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/inets/test/old_httpc_SUITE.erl3602
1 files changed, 0 insertions, 3602 deletions
diff --git a/lib/inets/test/old_httpc_SUITE.erl b/lib/inets/test/old_httpc_SUITE.erl
deleted file mode 100644
index 3d7de71052..0000000000
--- a/lib/inets/test/old_httpc_SUITE.erl
+++ /dev/null
@@ -1,3602 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-%%
-
-%%
-%% ts:run(inets, httpc_SUITE, [batch]).
-%%
-
--module(old_httpc_SUITE).
-
--include_lib("common_test/include/ct.hrl").
--include("test_server_line.hrl").
-
--include_lib("kernel/include/file.hrl").
--include("inets_test_lib.hrl").
-
-%% Note: This directive should only be used in test suites.
--compile(export_all).
-
-%% Test server specific exports
--define(IP_PORT, 8998).
--define(SSL_PORT, 8999).
--define(NOT_IN_USE_PORT, 8997).
--define(LOCAL_HOST, {127,0,0,1}).
--define(IPV6_LOCAL_HOST, "0:0:0:0:0:0:0:1").
--define(URL_START, "http://localhost:").
--define(SSL_URL_START, "https://localhost:").
--define(CR, $\r).
--define(LF, $\n).
--define(HTTP_MAX_HEADER_SIZE, 10240).
-
-
-%%--------------------------------------------------------------------
-%% all(Arg) -> [Doc] | [Case] | {skip, Comment}
-%% Arg - doc | suite
-%% Doc - string()
-%% Case - atom()
-%% Name of a test case function.
-%% Comment - string()
-%% Description: Returns documentation/test cases in this test suite
-%% or a skip tuple if the platform is not supported.
-%%--------------------------------------------------------------------
-
-suite() -> [{ct_hooks,[ts_install_cth]}].
-
-all() ->
- [
- http_options,
- %% http_head,
- %% http_get,
- %%http_post,
- %%http_post_streaming,
- %% http_dummy_pipe,
- %% http_inets_pipe,
- %% http_trace,
- %% http_async,
- %% http_save_to_file,
- %% http_save_to_file_async,
- %%http_headers,
- %%http_headers_dummy,
-
- %%http_bad_response,
-
- http_redirect,
- http_redirect_loop,
-
- %%http_internal_server_error,
- %%http_userinfo,
-
- %%http_cookie,
- %%http_server_does_not_exist,
- %%http_invalid_http,
- %%http_emulate_lower_versions,
- %%http_relaxed,
- %%page_does_not_exist,
- %%parse_url,
- options,
- %%headers_as_is,
- selecting_session,
-
- %%{group, ssl},
- %%{group, stream},
- {group, ipv6},
- {group, tickets},
- initial_server_connect
- ].
-
-groups() ->
- [
- %% {ssl, [], [ssl_head,
- %% essl_head,
- %% ssl_get,
- %% essl_get,
- %% ssl_trace,
- %% essl_trace]},
- %% {stream, [], [http_stream,
- %% http_stream_once]},
- {tickets, [], [%%hexed_query_otp_6191,
- %%empty_body_otp_6243,
- %%empty_response_header_otp_6830,
- %%transfer_encoding_otp_6807,
- %%no_content_204_otp_6982,
- %%missing_CR_otp_7304,
- %% {group, otp_7883},
- %% {group, otp_8154},
- %% {group, otp_8106},
- otp_8056,
- otp_8352,
- otp_8371,
- otp_8739]},
- %% {otp_7883, [], [otp_7883_1,
- %% otp_7883_2]},
- {otp_8154, [], [otp_8154_1]},
- %%{otp_8106, [], [otp_8106_pid,
- %% otp_8106_fun,
- %% otp_8106_mfa]},
- {ipv6, [], [ipv6_ipcomm, ipv6_essl]}
- ].
-
-
-init_per_group(ipv6 = _GroupName, Config) ->
- case inets_test_lib:has_ipv6_support() of
- {ok, _} ->
- Config;
- _ ->
- {skip, "Host does not support IPv6"}
- end;
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
-%%--------------------------------------------------------------------
-%% Function: init_per_suite(Config) -> Config
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Initiation before the whole suite
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-init_per_suite(Config) ->
-
- ?PRINT_SYSTEM_INFO([]),
-
- PrivDir = ?config(priv_dir, Config),
- DataDir = ?config(data_dir, Config),
- ServerRoot = filename:join(PrivDir, "server_root"),
- DocRoot = filename:join(ServerRoot, "htdocs"),
- IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
- SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
-
- setup_server_dirs(ServerRoot, DocRoot, DataDir),
- create_config(IpConfFile, ip_comm, ?IP_PORT, PrivDir, ServerRoot,
- DocRoot, DataDir),
- create_config(SslConfFile, ssl, ?SSL_PORT, PrivDir, ServerRoot,
- DocRoot, DataDir),
-
- Cgi = case test_server:os_type() of
- {win32, _} ->
- filename:join([ServerRoot, "cgi-bin", "cgi_echo.exe"]);
- _ ->
- filename:join([ServerRoot, "cgi-bin", "cgi_echo"])
- end,
-
- {ok, FileInfo} = file:read_file_info(Cgi),
- ok = file:write_file_info(Cgi, FileInfo#file_info{mode = 8#00755}),
-
- [{has_ipv6_support, inets_test_lib:has_ipv6_support()},
- {server_root, ServerRoot},
- {doc_root, DocRoot},
- {local_port, ?IP_PORT},
- {local_ssl_port, ?SSL_PORT} | Config].
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_suite(Config) -> _
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after the whole suite
-%%--------------------------------------------------------------------
-end_per_suite(Config) ->
- PrivDir = ?config(priv_dir, Config),
- inets_test_lib:del_dirs(PrivDir),
- application:stop(inets),
- application:stop(ssl),
- ok.
-
-
-%%--------------------------------------------------------------------
-%% Function: init_per_testcase(Case, Config) -> Config
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%%
-%% Description: Initiation before each test case
-%%
-%% Note: This function is free to add any key/value pairs to the Config
-%% variable, but should NOT alter/remove any existing entries.
-%%--------------------------------------------------------------------
-
-init_per_testcase(otp_8154_1 = Case, Config) ->
- init_per_testcase(Case, 5, Config);
-
-init_per_testcase(initial_server_connect = Case, Config) ->
- %% Try to check if crypto actually exist or not,
- %% this test case does not work unless it does
- try
- begin
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- inets:start(),
- Config
- end
- catch
- throw:{error, {failed_starting, App, ActualError}} ->
- tsp("init_per_testcase(~w) -> failed starting ~w: "
- "~n ~p", [Case, App, ActualError]),
- SkipString =
- "Could not start " ++ atom_to_list(App),
- skip(SkipString);
- _:X ->
- SkipString =
- lists:flatten(
- io_lib:format("Failed starting apps: ~p", [X])),
- skip(SkipString)
- end;
-
-init_per_testcase(Case, Config) ->
- init_per_testcase(Case, 2, Config).
-
-init_per_testcase(Case, Timeout, Config) ->
- io:format(user,
- "~n~n*** INIT ~w:~w[~w] ***"
- "~n~n", [?MODULE, Case, Timeout]),
-
- PrivDir = ?config(priv_dir, Config),
- application:stop(inets),
- Dog = test_server:timetrap(inets_test_lib:minutes(Timeout)),
- TmpConfig = lists:keydelete(watchdog, 1, Config),
- IpConfFile = integer_to_list(?IP_PORT) ++ ".conf",
- SslConfFile = integer_to_list(?SSL_PORT) ++ ".conf",
-
- %% inets:enable_trace(max, io, httpd),
- %% inets:enable_trace(max, io, httpc),
- %% inets:enable_trace(max, io, all),
-
- NewConfig =
- case atom_to_list(Case) of
- [$s, $s, $l | _] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- init_per_testcase_ssl(ssl, PrivDir, SslConfFile,
- [{watchdog, Dog} | TmpConfig]);
-
- [$e, $s, $s, $l | _] ->
- ?ENSURE_STARTED([crypto, public_key, ssl]),
- init_per_testcase_ssl(essl, PrivDir, SslConfFile,
- [{watchdog, Dog} | TmpConfig]);
-
- "ipv6_" ++ _Rest ->
- %% Ensure needed apps (crypto, public_key and ssl) are started
- try ?ENSURE_STARTED([crypto, public_key, ssl]) of
- ok ->
- Profile = ipv6,
- %% A stand-alone profile is represented by a pid()
- {ok, ProfilePid} =
- inets:start(httpc,
- [{profile, Profile},
- {data_dir, PrivDir}], stand_alone),
- ok = httpc:set_options([{ipfamily, inet6}],
- ProfilePid),
- tsp("httpc profile pid: ~p", [ProfilePid]),
- [{watchdog, Dog}, {profile, ProfilePid}| TmpConfig]
- catch
- throw:{error, {failed_starting, App, ActualError}} ->
- tsp("init_per_testcase(~w) -> failed starting ~w: "
- "~n ~p", [Case, App, ActualError]),
- SkipString =
- "Could not start " ++ atom_to_list(App),
- skip(SkipString);
- _:X ->
- SkipString =
- lists:flatten(
- io_lib:format("Failed starting apps: ~p", [X])),
- skip(SkipString)
- end;
-
- _ ->
- %% Try inet6fb4 on windows...
- %% No need? Since it is set above?
-
- %% tsp("init_per_testcase -> allways try IPv6 on windows"),
- %% ?RUN_ON_WINDOWS(
- %% fun() ->
- %% tsp("init_per_testcase:set_options_fun -> "
- %% "set-option ipfamily to inet6fb4"),
- %% Res = httpc:set_options([{ipfamily, inet6fb4}]),
- %% tsp("init_per_testcase:set_options_fun -> "
- %% "~n Res: ~p", [Res]),
- %% Res
- %% end),
-
- TmpConfig2 = lists:keydelete(local_server, 1, TmpConfig),
- %% Will start inets
- tsp("init_per_testcase -> try start server"),
- Server = start_http_server(PrivDir, IpConfFile),
- [{watchdog, Dog}, {local_server, Server} | TmpConfig2]
- end,
-
- %% <IPv6>
- %% Set default ipfamily to the same as the main server has by default
- %% This makes the client try w/ ipv6 before falling back to ipv4,
- %% as that is what the server is configured to do.
- %% Note that this is required for the tests to run on *BSD w/ ipv6 enabled
- %% as well as on Windows. The Linux behaviour of allowing ipv4 connects
- %% to ipv6 sockets is not required or even encouraged.
-
- tsp("init_per_testcase -> Options before ipfamily set: ~n~p",
- [httpc:get_options(all)]),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("init_per_testcase -> Options after ipfamily set: ~n~p",
- [httpc:get_options(all)]),
-
- %% Note that the IPv6 test case(s) *must* use inet6,
- %% so this value will be overwritten (see "ipv6_" below).
- %% </IPv6>
-
- %% inets:enable_trace(max, io, all),
- %% snmp:set_trace([gen_tcp]),
- tsp("init_per_testcase(~w) -> done when"
- "~n NewConfig: ~p"
- "~n~n", [Case, NewConfig]),
- NewConfig.
-
-
-init_per_testcase_ssl(Tag, PrivDir, SslConfFile, Config) ->
- tsp("init_per_testcase_ssl(~w) -> stop ssl", [Tag]),
- application:stop(ssl),
- Config2 = lists:keydelete(local_ssl_server, 1, Config),
- %% Will start inets
- tsp("init_per_testcase_ssl(~w) -> try start http server (including inets)",
- [Tag]),
- Server = inets_test_lib:start_http_server(
- filename:join(PrivDir, SslConfFile), Tag),
- tsp("init_per_testcase(~w) -> Server: ~p", [Tag, Server]),
- [{local_ssl_server, Server} | Config2].
-
-start_http_server(ConfDir, ConfFile) ->
- inets_test_lib:start_http_server( filename:join(ConfDir, ConfFile) ).
-
-
-%%--------------------------------------------------------------------
-%% Function: end_per_testcase(Case, Config) -> _
-%% Case - atom()
-%% Name of the test case that is about to be run.
-%% Config - [tuple()]
-%% A list of key/value pairs, holding the test case configuration.
-%% Description: Cleanup after each test case
-%%--------------------------------------------------------------------
-end_per_testcase(http_save_to_file = Case, Config) ->
- io:format(user, "~n~n*** END ~w:~w ***~n~n",
- [?MODULE, Case]),
- PrivDir = ?config(priv_dir, Config),
- FullPath = filename:join(PrivDir, "dummy.html"),
- file:delete(FullPath),
- finish(Config);
-
-end_per_testcase(Case, Config) ->
- io:format(user, "~n~n*** END ~w:~w ***~n~n",
- [?MODULE, Case]),
- case atom_to_list(Case) of
- "ipv6_" ++ _Rest ->
- tsp("end_per_testcase(~w) -> stop ssl", [Case]),
- application:stop(ssl),
- tsp("end_per_testcase(~w) -> stop public_key", [Case]),
- application:stop(public_key),
- tsp("end_per_testcase(~w) -> stop crypto", [Case]),
- application:stop(crypto),
- ProfilePid = ?config(profile, Config),
- tsp("end_per_testcase(~w) -> stop httpc profile (~p)",
- [Case, ProfilePid]),
- unlink(ProfilePid),
- inets:stop(stand_alone, ProfilePid),
- tsp("end_per_testcase(~w) -> httpc profile (~p) stopped",
- [Case, ProfilePid]),
- ok;
- _ ->
- ok
- end,
- finish(Config).
-
-finish(Config) ->
- Dog = ?config(watchdog, Config),
- case Dog of
- undefined ->
- ok;
- _ ->
- tsp("finish -> stop watchdog (~p)", [Dog]),
- test_server:timetrap_cancel(Dog)
- end.
-
-%%-------------------------------------------------------------------------
-%% Test cases starts here.
-%%-------------------------------------------------------------------------
-
-
-
-%%-------------------------------------------------------------------------
-
-http_options(doc) ->
- ["Test http options request against local server."];
-http_options(suite) ->
- [];
-http_options(Config) when is_list(Config) ->
- skip("Not supported by httpd").
-
-http_head(doc) ->
- ["Test http head request against local server."];
-http_head(suite) ->
- [];
-http_head(Config) when is_list(Config) ->
- tsp("http_head -> entry with"
- "~n Config: ~p", [Config]),
- Method = head,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HttpOpts = [],
- Opts = [],
- VerifyResult =
- fun({ok, {{_,200,_}, [_ | _], []}}) ->
- ok;
- ({ok, UnexpectedReply}) ->
- tsp("http_head:verify_fun -> Unexpected Reply: "
- "~n ~p", [UnexpectedReply]),
- tsf({unexpected_reply, UnexpectedReply});
- ({error, Reason} = Error) ->
- tsp("http_head:verify_fun -> Error reply: "
- "~n Reason: ~p", [Reason]),
- tsf({bad_reply, Error})
- end,
- simple_request_and_verify(Config,
- Method, Request, HttpOpts, Opts, VerifyResult).
-
-
-%%-------------------------------------------------------------------------
-
-http_get(doc) ->
- ["Test http get request against local server"];
-http_get(suite) ->
- [];
-http_get(Config) when is_list(Config) ->
- tsp("http_get -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- tsp("local-server running"),
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- Timeout = timer:seconds(1),
- ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout},
- {connect_timeout, ConnTimeout}],
- Options1 = [],
- Body =
- case httpc:request(Method, Request, HttpOptions1, Options1) of
- {ok, {{_,200,_}, [_ | _], ReplyBody = [_ | _]}} ->
- ReplyBody;
- {ok, UnexpectedReply1} ->
- tsf({unexpected_reply, UnexpectedReply1});
- {error, _} = Error1 ->
- tsf({bad_reply, Error1})
- end,
-
- %% eqvivivalent to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(Body),
-
- HttpOptions2 = [],
- Options2 = [{body_format, binary}],
- case httpc:request(Method, Request, HttpOptions2, Options2) of
- {ok, {{_,200,_}, [_ | _], Bin}} when is_binary(Bin) ->
- ok;
- {ok, {{_,200,_}, [_ | _], BadBin}} ->
- tsf({body_format_not_binary, BadBin});
- {ok, UnexpectedReply2} ->
- tsf({unexpected_reply, UnexpectedReply2});
- {error, _} = Error2 ->
- tsf({bad_reply, Error2})
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-%%-------------------------------------------------------------------------
-
-http_post(doc) ->
- ["Test http post request against local server. We do in this case "
- "only care about the client side of the the post. The server "
- "script will not actually use the post data."];
-http_post(suite) ->
- [];
-http_post(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
-
- URL = case test_server:os_type() of
- {win32, _} ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo.exe";
- _ ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo"
-
- end,
- %% Cgi-script expects the body length to be 100
- Body = lists:duplicate(100, "1"),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(post, {URL, [{"expect","100-continue"}],
- "text/plain", Body}, [], []),
-
- {ok, {{_,504,_}, [_ | _], []}} =
- httpc:request(post, {URL, [{"expect","100-continue"}],
- "text/plain", "foobar"}, [], []);
- _ ->
- skip("Failed to start local http-server")
- end.
-
-%%-------------------------------------------------------------------------
-http_post_streaming(doc) ->
- ["Test streaming http post request against local server. "
- "We only care about the client side of the the post. "
- "The server script will not actually use the post data."];
-http_post_streaming(suite) ->
- [];
-http_post_streaming(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = case test_server:os_type() of
- {win32, _} ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo.exe";
- _ ->
- ?URL_START ++ integer_to_list(Port) ++
- "/cgi-bin/cgi_echo"
- end,
- %% Cgi-script expects the body length to be 100
- BodyFun = fun(0) ->
- io:format("~w:http_post_streaming_fun -> "
- "zero~n", [?MODULE]),
- eof;
- (LenLeft) ->
- io:format("~w:http_post_streaming_fun -> "
- "LenLeft: ~p~n", [?MODULE, LenLeft]),
- {ok, lists:duplicate(10, "1"), LenLeft - 10}
- end,
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(post, {URL,
- [{"expect", "100-continue"},
- {"content-length", "100"}],
- "text/plain", {BodyFun, 100}}, [], []),
-
- {ok, {{_,504,_}, [_ | _], []}} =
- httpc:request(post, {URL,
- [{"expect", "100-continue"},
- {"content-length", "10"}],
- "text/plain", {BodyFun, 10}}, [], []);
-
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-http_emulate_lower_versions(doc) ->
- ["Perform request as 0.9 and 1.0 clients."];
-http_emulate_lower_versions(suite) ->
- [];
-http_emulate_lower_versions(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, Body0} =
- httpc:request(get, {URL, []}, [{version, "HTTP/0.9"}], []),
- inets_test_lib:check_body(Body0),
- {ok, {{"HTTP/1.0", 200, _}, [_ | _], Body1 = [_ | _]}} =
- httpc:request(get, {URL, []}, [{version, "HTTP/1.0"}], []),
- inets_test_lib:check_body(Body1),
- {ok, {{"HTTP/1.1", 200, _}, [_ | _], Body2 = [_ | _]}} =
- httpc:request(get, {URL, []}, [{version, "HTTP/1.1"}], []),
- inets_test_lib:check_body(Body2);
- _->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-
-http_relaxed(doc) ->
- ["Test relaxed mode"];
-http_relaxed(suite) ->
- [];
-http_relaxed(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
- %% ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/missing_reason_phrase.html",
-
- {error, Reason} =
- httpc:request(get, {URL, []}, [{relaxed, false}], []),
-
- test_server:format("Not relaxed: ~p~n", [Reason]),
-
- {ok, {{_, 200, _}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, []}, [{relaxed, true}], []),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipv6, enabled}]),
- %% ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-http_dummy_pipe(doc) ->
- ["Test pipelining code."];
-http_dummy_pipe(suite) ->
- [];
-http_dummy_pipe(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/foobar.html",
-
- test_pipeline(URL),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-http_inets_pipe(doc) ->
- ["Test pipelining code."];
-http_inets_pipe(suite) ->
- [];
-http_inets_pipe(Config) when is_list(Config) ->
-
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- test_pipeline(URL);
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-test_pipeline(URL) ->
- p("test_pipeline -> entry with"
- "~n URL: ~p", [URL]),
-
- httpc:set_options([{pipeline_timeout, 50000},
- {max_pipeline_length, 5}]),
-
- p("test_pipeline -> issue (async) request 1"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdA1} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdA1: ~p", [RequestIdA1]),
- p("test_pipeline -> RequestIdA1: ~p"
- "~n when profile info: ~p", [RequestIdA1, httpc:info()]),
-
- %% Make sure pipeline is initiated
- p("test_pipeline -> sleep some", []),
- test_server:sleep(4000),
-
- p("test_pipeline -> issue (async) request A2, A3 and A4"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdA2} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdA3} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdA4} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p",
- [RequestIdA2, RequestIdA3, RequestIdA4]),
- p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p"
- "~n when profile info: ~p",
- [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]),
-
- p("test_pipeline -> issue (sync) request 3"),
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, []}, [], []),
-
- p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4"
- "~n when profile info: ~p", [httpc:info()]),
- pipeline_await_async_reply([{RequestIdA1, a1, 200},
- {RequestIdA2, a2, 200},
- {RequestIdA3, a3, 200},
- {RequestIdA4, a4, 200}], ?MINS(2)),
-
- p("test_pipeline -> sleep some"
- "~n when profile info: ~p", [httpc:info()]),
- test_server:sleep(4000),
-
- p("test_pipeline -> issue (async) request B1, B2, B3 and B4"
- "~n when profile info: ~p", [httpc:info()]),
- {ok, RequestIdB1} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB2} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB3} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- {ok, RequestIdB4} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p",
- [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]),
- p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p"
- "~n when profile info: ~p",
- [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]),
-
- p("test_pipeline -> cancel (async) request B2"
- "~n when profile info: ~p", [httpc:info()]),
- ok = httpc:cancel_request(RequestIdB2),
-
- p("test_pipeline -> "
- "expect *no* reply for cancelled (async) request B2 (for 3 secs)"
- "~n when profile info: ~p", [httpc:info()]),
- receive
- {http, {RequestIdB2, _}} ->
- tsf(http_cancel_request_failed)
- after 3000 ->
- ok
- end,
-
- p("test_pipeline -> expect reply for (async) request B1, B3 and B4"
- "~n when profile info: ~p", [httpc:info()]),
- Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200},
- {RequestIdB3, b3, 200},
- {RequestIdB4, b4, 200}], ?MINS(1)),
- [{b1, Body}|_] = Bodies,
-
- p("test_pipeline -> check reply for (async) request B1"
- "~n when profile info: ~p", [httpc:info()]),
- inets_test_lib:check_body(binary_to_list(Body)),
-
- p("test_pipeline -> ensure no unexpected incomming"
- "~n when profile info: ~p", [httpc:info()]),
- receive
- {http, Any} ->
- tsf({unexpected_message, Any})
- after 500 ->
- ok
- end,
-
- p("test_pipeline -> done"
- "~n when profile info: ~p", [httpc:info()]),
- ok.
-
-pipeline_await_async_reply(ReqIds, Timeout) ->
- pipeline_await_async_reply(ReqIds, Timeout, []).
-
-pipeline_await_async_reply([], _, Acc) ->
- lists:keysort(1, Acc);
-pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 ->
- T1 = inets_test_lib:timestamp(),
- p("pipeline_await_async_reply -> await replies"
- "~n ReqIds: ~p"
- "~n Timeout: ~p", [ReqIds, Timeout]),
- receive
- {http, {RequestId, {{_, Status, _}, _, Body}}} ->
- p("pipeline_await_async_reply -> received reply for"
- "~n RequestId: ~p"
- "~n Status: ~p", [RequestId, Status]),
- case lists:keysearch(RequestId, 1, ReqIds) of
- {value, {RequestId, N, Status}} ->
- p("pipeline_await_async_reply -> "
- "found expected request ~w", [N]),
- ReqIds2 = lists:keydelete(RequestId, 1, ReqIds),
- NewTimeout = Timeout - (inets_test_lib:timestamp()-T1),
- pipeline_await_async_reply(ReqIds2, NewTimeout,
- [{N, Body} | Acc]);
- {value, {RequestId, N, WrongStatus}} ->
- p("pipeline_await_async_reply -> "
- "found request ~w with wrong status", [N]),
- tsf({reply_with_unexpected_status,
- {RequestId, N, WrongStatus}});
- false ->
- tsf({unexpected_reply, {RequestId, Status}})
- end;
- {http, Msg} ->
- tsf({unexpected_reply, Msg})
- after Timeout ->
- receive
- Any ->
- tsp("pipeline_await_async_reply -> "
- "received unknown data after timeout: "
- "~n ~p", [Any]),
- tsf({timeout, {unknown, Any}})
- end
- end;
-pipeline_await_async_reply(ReqIds, _, Acc) ->
- tsp("pipeline_await_async_reply -> "
- "timeout: "
- "~n ~p"
- "~nwhen"
- "~n ~p", [ReqIds, Acc]),
- tsf({timeout, ReqIds, Acc}).
-
-
-
-%%-------------------------------------------------------------------------
-http_trace(doc) ->
- ["Perform a TRACE request."];
-http_trace(suite) ->
- [];
-http_trace(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- case httpc:request(trace, {URL, []}, [], []) of
- {ok, {{_,200,_}, [_ | _], "TRACE /dummy.html" ++ _}} ->
- ok;
- {ok, {{_,200,_}, [_ | _], WrongBody}} ->
- tsf({wrong_body, WrongBody});
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
-%%-------------------------------------------------------------------------
-http_async(doc) ->
- ["Test an asynchrony http request."];
-http_async(suite) ->
- [];
-http_async(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
-
- Body =
- receive
- {http, {RequestId, {{_, 200, _}, _, BinBody}}} ->
- BinBody;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- inets_test_lib:check_body(binary_to_list(Body)),
-
- {ok, NewRequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false}]),
- ok = httpc:cancel_request(NewRequestId),
- receive
- {http, {NewRequestId, _NewResult}} ->
- tsf(http_cancel_request_failed)
- after 3000 ->
- ok
- end;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-%%-------------------------------------------------------------------------
-http_save_to_file(doc) ->
- ["Test to save the http body to a file"];
-http_save_to_file(suite) ->
- [];
-http_save_to_file(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- PrivDir = ?config(priv_dir, Config),
- FilePath = filename:join(PrivDir, "dummy.html"),
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, saved_to_file}
- = httpc:request(get, {URL, []}, [], [{stream, FilePath}]),
- {ok, Bin} = file:read_file(FilePath),
- {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
- Bin == Body;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-http_save_to_file_async(doc) ->
- ["Test to save the http body to a file"];
-http_save_to_file_async(suite) ->
- [];
-http_save_to_file_async(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- PrivDir = ?config(priv_dir, Config),
- FilePath = filename:join(PrivDir, "dummy.html"),
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, RequestId} = httpc:request(get, {URL, []}, [],
- [{stream, FilePath},
- {sync, false}]),
- receive
- {http, {RequestId, saved_to_file}} ->
- ok;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- {ok, Bin} = file:read_file(FilePath),
- {ok, {{_,200,_}, [_ | _], Body}} = httpc:request(URL),
- Bin == Body;
- _ ->
- skip("Failed to start local http-server")
- end.
-%%-------------------------------------------------------------------------
-http_headers(doc) ->
- ["Use as many request headers as possible not used in proxy_headers"];
-http_headers(suite) ->
- [];
-http_headers(Config) when is_list(Config) ->
-
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- DocRoot = ?config(doc_root, Config),
- {ok, FileInfo} =
- file:read_file_info(filename:join([DocRoot,"dummy.html"])),
- CreatedSec =
- calendar:datetime_to_gregorian_seconds(
- FileInfo#file_info.mtime),
-
- Mod = httpd_util:rfc1123_date(
- calendar:gregorian_seconds_to_datetime(
- CreatedSec-1)),
-
- Date = httpd_util:rfc1123_date({date(), time()}),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-Modified-Since",
- Mod},
- {"From","[email protected]"},
- {"Date", Date}
- ]}, [], []),
-
- Mod1 = httpd_util:rfc1123_date(
- calendar:gregorian_seconds_to_datetime(
- CreatedSec+1)),
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-UnModified-Since",
- Mod1}
- ]}, [], []),
-
- Tag = httpd_util:create_etag(FileInfo),
-
-
- {ok, {{_,200,_}, [_ | _], [_ | _]}} =
- httpc:request(get, {URL, [{"If-Match",
- Tag}
- ]}, [], []),
-
- {ok, {{_,200,_}, [_ | _], _}} =
- httpc:request(get, {URL, [{"If-None-Match",
- "NotEtag,NeihterEtag"},
- {"Connection", "Close"}
- ]}, [], []),
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-%%-------------------------------------------------------------------------
-http_headers_dummy(doc) ->
- ["Test the code for handling headers we do not want/can send "
- "to a real server. Note it is not logical to send"
- "all of these headers together, we only want to test that"
- "the code for handling headers will not crash."];
-http_headers_dummy(suite) ->
- [];
-http_headers_dummy(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy_headers.html",
-
- Foo = http_chunk:encode("foobar") ++
- binary_to_list(http_chunk:encode_last()),
- FooBar = Foo ++ "\r\n\r\nOther:inets_test\r\n\r\n",
-
- UserPasswd = base64:encode_to_string("Alladin:Sesame"),
- Auth = "Basic " ++ UserPasswd,
-
- %% The dummy server will ignore the headers, we only want to test
- %% that the client header-handling code. This would not
- %% be a vaild http-request!
- {ok, {{_,200,_}, [_ | _], [_|_]}} =
- httpc:request(post,
- {URL,
- [{"Via",
- "1.0 fred, 1.1 nowhere.com (Apache/1.1)"},
- {"Warning","1#pseudonym foobar"},
- {"Vary","*"},
- {"Upgrade","HTTP/2.0"},
- {"Pragma", "1#no-cache"},
- {"Cache-Control", "no-cache"},
- {"Connection", "close"},
- {"Date", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Accept", " text/plain; q=0.5, text/html"},
- {"Accept-Language", "en"},
- {"Accept-Encoding","chunked"},
- {"Accept-Charset", "ISO8859-1"},
- {"Authorization", Auth},
- {"Expect", "1#100-continue"},
- {"User-Agent","inets"},
- {"Transfer-Encoding","chunked"},
- {"Range", " bytes=0-499"},
- {"If-Range", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"If-Match", "*"},
- {"Content-Type", "text/plain"},
- {"Content-Encoding", "chunked"},
- {"Content-Length", "6"},
- {"Content-Language", "en"},
- {"Content-Location", "http://www.foobar.se"},
- {"Content-MD5",
- "104528739076276072743283077410617235478"},
- {"Content-Range", "bytes 0-499/1234"},
- {"Allow", "GET"},
- {"Proxy-Authorization", Auth},
- {"Expires", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Upgrade", "HTTP/2.0"},
- {"Last-Modified", "Sat, 29 Oct 1994 19:43:31 GMT"},
- {"Trailer","1#User-Agent"}
- ], "text/plain", FooBar},
- [], []),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-http_bad_response(doc) ->
- ["Test what happens when the server does not follow the protocol"];
-http_bad_response(suite) ->
- [];
-http_bad_response(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_crlf.html",
-
- URL1 = ?URL_START ++ integer_to_list(Port) ++ "/wrong_statusline.html",
-
- {error, timeout} = httpc:request(get, {URL, []}, [{timeout, 400}], []),
-
- {error, Reason} = httpc:request(URL1),
-
- test_server:format("Wrong Statusline: ~p~n", [Reason]),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-ssl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-ssl_head(suite) ->
- [];
-ssl_head(Config) when is_list(Config) ->
- ssl_head(ssl, Config).
-
-essl_head(doc) ->
- ["Same as http_head/1 but over ssl sockets."];
-essl_head(suite) ->
- [];
-essl_head(Config) when is_list(Config) ->
- ssl_head(essl, Config).
-
-ssl_head(SslTag, Config) ->
- tsp("ssl_head -> entry with"
- "~n SslTag: ~p"
- "~n Config: ~p", [SslTag, Config]),
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_head -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- {ok, {{_,200, _}, [_ | _], []}} =
- httpc:request(head, {URL, []}, [{ssl, SSLConfig}], []);
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
-
-
-%%-------------------------------------------------------------------------
-ssl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-ssl_get(suite) ->
- [];
-ssl_get(Config) when is_list(Config) ->
- ssl_get(ssl, Config).
-
-essl_get(doc) ->
- ["Same as http_get/1 but over ssl sockets."];
-essl_get(suite) ->
- [];
-essl_get(Config) when is_list(Config) ->
- ssl_get(essl, Config).
-
-ssl_get(SslTag, Config) when is_list(Config) ->
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_get -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- case httpc:request(get, {URL, []}, [{ssl, SSLConfig}], []) of
- {ok, {{_,200, _}, [_ | _], Body = [_ | _]}} ->
- inets_test_lib:check_body(Body),
- ok;
- {ok, {StatusLine, Headers, _Body}} ->
- tsp("ssl_get -> unexpected result: "
- "~n StatusLine: ~p"
- "~n Headers: ~p", [StatusLine, Headers]),
- tsf({unexpected_response, StatusLine, Headers});
- {error, Reason} ->
- tsp("ssl_get -> request failed: "
- "~n Reason: ~p", [Reason]),
- tsf({request_failed, Reason})
- end;
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
-
-
-%%-------------------------------------------------------------------------
-ssl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-ssl_trace(suite) ->
- [];
-ssl_trace(Config) when is_list(Config) ->
- ssl_trace(ssl, Config).
-
-essl_trace(doc) ->
- ["Same as http_trace/1 but over ssl sockets."];
-essl_trace(suite) ->
- [];
-essl_trace(Config) when is_list(Config) ->
- ssl_trace(essl, Config).
-
-ssl_trace(SslTag, Config) when is_list(Config) ->
- case ?config(local_ssl_server, Config) of
- ok ->
- DataDir = ?config(data_dir, Config),
- Port = ?config(local_ssl_port, Config),
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig =
- case SslTag of
- ssl ->
- SSLOptions;
- essl ->
- {essl, SSLOptions}
- end,
- tsp("ssl_trace -> make request using: "
- "~n URL: ~p"
- "~n SslTag: ~p"
- "~n SSLOptions: ~p", [URL, SslTag, SSLOptions]),
- case httpc:request(trace, {URL, []}, [{ssl, SSLConfig}], []) of
- {ok, {{_,200, _}, [_ | _], "TRACE /dummy.html" ++ _}} ->
- ok;
- {ok, {{_,200,_}, [_ | _], WrongBody}} ->
- tsf({wrong_body, WrongBody});
- {ok, WrongReply} ->
- tsf({wrong_reply, WrongReply});
- Error ->
- tsf({failed, Error})
- end;
- {ok, _} ->
- skip("local http-server not started");
- _ ->
- skip("SSL not started")
- end.
-
-
-%%-------------------------------------------------------------------------
-http_redirect(doc) ->
- ["Test redirect with dummy server as httpd does not implement"
- " server redirect"];
-http_redirect(suite) ->
- [];
-http_redirect(Config) when is_list(Config) ->
- tsp("http_redirect -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- %% tsp("http_redirect -> set ipfamily option to inet"),
- %% ok = httpc:set_options([{ipfamily, inet}]),
-
- tsp("http_redirect -> start dummy server inet"),
- {DummyServerPid, Port} = dummy_server(ipv4),
- tsp("http_redirect -> server port = ~p", [Port]),
-
- URL300 = ?URL_START ++ integer_to_list(Port) ++ "/300.html",
-
- tsp("http_redirect -> issue request 1: "
- "~n ~p", [URL300]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL300, []}, [], []),
-
- tsp("http_redirect -> issue request 2: "
- "~n ~p", [URL300]),
- {ok, {{_,300,_}, [_ | _], _}} =
- httpc:request(get, {URL300, []}, [{autoredirect, false}], []),
-
- URL301 = ?URL_START ++ integer_to_list(Port) ++ "/301.html",
-
- tsp("http_redirect -> issue request 3: "
- "~n ~p", [URL301]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL301, []}, [], []),
-
- tsp("http_redirect -> issue request 4: "
- "~n ~p", [URL301]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL301, []}, [], []),
-
- tsp("http_redirect -> issue request 5: "
- "~n ~p", [URL301]),
- {ok, {{_,301,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL301, [],"text/plain", "foobar"},
- [], []),
-
- URL302 = ?URL_START ++ integer_to_list(Port) ++ "/302.html",
-
- tsp("http_redirect -> issue request 6: "
- "~n ~p", [URL302]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL302, []}, [], []),
- case httpc:request(get, {URL302, []}, [], []) of
- {ok, Reply7} ->
- case Reply7 of
- {{_,200,_}, [_ | _], [_|_]} ->
- tsp("http_redirect -> "
- "expected reply for request 7"),
- ok;
- {StatusLine, Headers, Body} ->
- tsp("http_redirect -> "
- "unexpected reply for request 7: "
- "~n StatusLine: ~p"
- "~n Headers: ~p"
- "~n Body: ~p",
- [StatusLine, Headers, Body]),
- tsf({unexpected_reply, Reply7})
- end;
- Error7 ->
- tsp("http_redirect -> "
- "unexpected result for request 7: "
- "~n Error7: ~p",
- [Error7]),
- tsf({unexpected_result, Error7})
- end,
-
- tsp("http_redirect -> issue request 7: "
- "~n ~p", [URL302]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL302, []}, [], []),
-
- tsp("http_redirect -> issue request 8: "
- "~n ~p", [URL302]),
- {ok, {{_,302,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL302, [],"text/plain", "foobar"},
- [], []),
-
- URL303 = ?URL_START ++ integer_to_list(Port) ++ "/303.html",
-
- tsp("http_redirect -> issue request 9: "
- "~n ~p", [URL303]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL303, []}, [], []),
-
- tsp("http_redirect -> issue request 10: "
- "~n ~p", [URL303]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL303, []}, [], []),
-
- tsp("http_redirect -> issue request 11: "
- "~n ~p", [URL303]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL303, [],"text/plain", "foobar"},
- [], []),
-
- URL307 = ?URL_START ++ integer_to_list(Port) ++ "/307.html",
-
- tsp("http_redirect -> issue request 12: "
- "~n ~p", [URL307]),
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URL307, []}, [], []),
-
- tsp("http_redirect -> issue request 13: "
- "~n ~p", [URL307]),
- {ok, {{_,200,_}, [_ | _], []}}
- = httpc:request(head, {URL307, []}, [], []),
-
- tsp("http_redirect -> issue request 14: "
- "~n ~p", [URL307]),
- {ok, {{_,307,_}, [_ | _], [_|_]}}
- = httpc:request(post, {URL307, [],"text/plain", "foobar"},
- [], []),
-
- tsp("http_redirect -> stop dummy server"),
- DummyServerPid ! stop,
- tsp("http_redirect -> reset ipfamily option (to inet6fb4)"),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("http_redirect -> done"),
- ok;
-
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-
-%%-------------------------------------------------------------------------
-http_redirect_loop(doc) ->
- ["Test redirect loop detection"];
-http_redirect_loop(suite) ->
- [];
-http_redirect_loop(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/redirectloop.html",
-
- {ok, {{_,300,_}, [_ | _], _}}
- = httpc:request(get, {URL, []}, [], []),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-%%-------------------------------------------------------------------------
-http_internal_server_error(doc) ->
- ["Test 50X codes"];
-http_internal_server_error(suite) ->
- [];
-http_internal_server_error(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL500 = ?URL_START ++ integer_to_list(Port) ++ "/500.html",
-
- {ok, {{_,500,_}, [_ | _], _}}
- = httpc:request(get, {URL500, []}, [], []),
-
-
- URL503 = ?URL_START ++ integer_to_list(Port) ++ "/503.html",
-
- %% Used to be able to make the service available after retry.
- ets:new(unavailable, [named_table, public, set]),
- ets:insert(unavailable, {503, unavailable}),
-
- {ok, {{_,200, _}, [_ | _], [_|_]}} =
- httpc:request(get, {URL503, []}, [], []),
-
- ets:insert(unavailable, {503, long_unavailable}),
-
- {ok, {{_,503, _}, [_ | _], [_|_]}} =
- httpc:request(get, {URL503, []}, [], []),
-
- ets:delete(unavailable),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-http_userinfo(doc) ->
- ["Test user info e.i. http://user:passwd@host:port/"];
-http_userinfo(suite) ->
- [];
-http_userinfo(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
-
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URLAuth = "http://alladin:sesame@localhost:"
- ++ integer_to_list(Port) ++ "/userinfo.html",
-
- {ok, {{_,200,_}, [_ | _], _}}
- = httpc:request(get, {URLAuth, []}, [], []),
-
- URLUnAuth = "http://alladin:foobar@localhost:"
- ++ integer_to_list(Port) ++ "/userinfo.html",
-
- {ok, {{_,401, _}, [_ | _], _}} =
- httpc:request(get, {URLUnAuth, []}, [], []),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-http_cookie(doc) ->
- ["Test cookies."];
-http_cookie(suite) ->
- [];
-http_cookie(Config) when is_list(Config) ->
- ok = httpc:set_options([{cookies, enabled}, {ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URLStart = ?URL_START
- ++ integer_to_list(Port),
-
- URLCookie = URLStart ++ "/cookie.html",
-
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URLCookie, []}, [], []),
-
- ets:new(cookie, [named_table, public, set]),
- ets:insert(cookie, {cookies, true}),
-
- {ok, {{_,200,_}, [_ | _], [_|_]}}
- = httpc:request(get, {URLStart ++ "/", []}, [], []),
-
- ets:delete(cookie),
-
- ok = httpc:set_options([{cookies, disabled}]),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-%%-------------------------------------------------------------------------
-http_server_does_not_exist(doc) ->
- ["Test that we get an error message back when the server "
- "does note exist."];
-http_server_does_not_exist(suite) ->
- [];
-http_server_does_not_exist(Config) when is_list(Config) ->
- {error, _} =
- httpc:request(get, {"http://localhost:" ++
- integer_to_list(?NOT_IN_USE_PORT)
- ++ "/", []},[], []),
- ok.
-
-
-%%-------------------------------------------------------------------------
-page_does_not_exist(doc) ->
- ["Test that we get a 404 when the page is not found."];
-page_does_not_exist(suite) ->
- [];
-page_does_not_exist(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/doesnotexist.html",
- {ok, {{_,404,_}, [_ | _], [_ | _]}}
- = httpc:request(get, {URL, []}, [], []),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-http_stream(doc) ->
- ["Test the option stream for asynchrony requests"];
-http_stream(suite) ->
- [];
-http_stream(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_ | _], Body}} =
- httpc:request(get, {URL, []}, [], []),
-
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false},
- {stream, self}]),
-
- receive
- {http, {RequestId, stream_start, _Headers}} ->
- ok;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- StreamedBody = receive_streamed_body(RequestId, <<>>),
-
- Body == binary_to_list(StreamedBody).
-
-
-%%-------------------------------------------------------------------------
-
-http_stream_once(doc) ->
- ["Test the option stream for asynchrony requests"];
-http_stream_once(suite) ->
- [];
-http_stream_once(Config) when is_list(Config) ->
- p("http_stream_once -> entry with"
- "~n Config: ~p", [Config]),
-
- p("http_stream_once -> set ipfamily to inet", []),
- ok = httpc:set_options([{ipfamily, inet}]),
- p("http_stream_once -> start dummy server", []),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- PortStr = integer_to_list(Port),
- p("http_stream_once -> once", []),
- once(?URL_START ++ PortStr ++ "/once.html"),
- p("http_stream_once -> once_chunked", []),
- once(?URL_START ++ PortStr ++ "/once_chunked.html"),
- p("http_stream_once -> dummy", []),
- once(?URL_START ++ PortStr ++ "/dummy.html"),
-
- p("http_stream_once -> stop dummy server", []),
- DummyServerPid ! stop,
- p("http_stream_once -> set ipfamily to inet6fb4", []),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- p("http_stream_once -> done", []),
- ok.
-
-once(URL) ->
- p("once -> issue sync request for ~p", [URL]),
- {ok, {{_,200,_}, [_ | _], Body}} =
- httpc:request(get, {URL, []}, [], []),
-
- p("once -> issue async (self stream) request for ~p", [URL]),
- {ok, RequestId} =
- httpc:request(get, {URL, []}, [], [{sync, false},
- {stream, {self, once}}]),
-
- p("once -> await stream_start reply for (async) request ~p", [RequestId]),
- NewPid =
- receive
- {http, {RequestId, stream_start, _Headers, Pid}} ->
- p("once -> received stream_start reply for (async) request ~p: ~p",
- [RequestId, Pid]),
- Pid;
- {http, Msg} ->
- tsf(Msg)
- end,
-
- tsp("once -> request handler: ~p", [NewPid]),
-
- p("once -> await stream reply for (async) request ~p", [RequestId]),
- BodyPart =
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- p("once -> received stream reply for (async) request ~p: "
- "~n~p", [RequestId, binary_to_list(BinBodyPart)]),
- BinBodyPart
- end,
-
- tsp("once -> first body part '~p' received", [binary_to_list(BodyPart)]),
-
- StreamedBody = receive_streamed_body(RequestId, BinBodyPart, NewPid),
-
- Body = binary_to_list(StreamedBody),
-
- p("once -> done when Bode: ~p", [Body]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-parse_url(doc) ->
- ["Test that an url is parsed correctly"];
-parse_url(suite) ->
- [];
-parse_url(Config) when is_list(Config) ->
- %% ipv6
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html"),
- {ok, {http,[],"[2010:836B:4179::836B:4179]",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{ipv6_host_with_brackets, true}]),
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{ipv6_host_with_brackets, false}]),
- {ok, {http,[],"2010:836B:4179::836B:4179",80,"/foobar.html",[]}} =
- http_uri:parse("http://[2010:836B:4179::836B:4179]/foobar.html",
- [{foo, false}]),
- {error,
- {malformed_url, _, "http://2010:836B:4179::836B:4179/foobar.html"}} =
- http_uri:parse("http://2010:836B:4179::836B:4179/foobar.html"),
-
- %% ipv4
- {ok, {http,[],"127.0.0.1",80,"/foobar.html",[]}} =
- http_uri:parse("http://127.0.0.1/foobar.html"),
-
- %% host
- {ok, {http,[],"localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://localhost:8888/foobar.html"),
-
- %% Userinfo
- {ok, {http,"nisse:foobar","localhost",8888,"/foobar.html",[]}} =
- http_uri:parse("http://nisse:foobar@localhost:8888/foobar.html"),
-
- %% Scheme error
- {error, no_scheme} = http_uri:parse("localhost/foobar.html"),
- {error, {malformed_url, _, _}} =
- http_uri:parse("localhost:8888/foobar.html"),
-
- %% Query
- {ok, {http,[],"localhost",8888,"/foobar.html","?foo=bar&foobar=42"}} =
- http_uri:parse("http://localhost:8888/foobar.html?foo=bar&foobar=42"),
-
- %% Esc chars
- {ok, {http,[],"www.somedomain.com",80,"/%2Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%2Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%252Eabc",[]}} =
- http_uri:parse("http://www.somedomain.com/%252Eabc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc",[]}} =
- http_uri:parse("http://www.somedomain.com/%25abc"),
- {ok, {http,[],"www.somedomain.com",80,"/%25abc", "?foo=bar"}} =
- http_uri:parse("http://www.somedomain.com/%25abc?foo=bar"),
-
-
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-ipv6_ipcomm() ->
- [{require, ipv6_hosts}].
-ipv6_ipcomm(doc) ->
- ["Test ip_comm ipv6."];
-ipv6_ipcomm(suite) ->
- [];
-ipv6_ipcomm(Config) when is_list(Config) ->
- HTTPOptions = [],
- SocketType = ip_comm,
- Scheme = "http",
- Extra = [],
- ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
-
-
-%%-------------------------------------------------------------------------
-
-ipv6_essl() ->
- [{require, ipv6_hosts}].
-ipv6_essl(doc) ->
- ["Test essl ipv6."];
-ipv6_essl(suite) ->
- [];
-ipv6_essl(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- CertFile = filename:join(DataDir, "ssl_client_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
- SSLConfig = {essl, SSLOptions},
- tsp("ssl_ipv6 -> make request using: "
- "~n SSLOptions: ~p", [SSLOptions]),
- HTTPOptions = [{ssl, SSLConfig}],
- SocketType = essl,
- Scheme = "https",
- Extra = SSLOptions,
- ipv6(SocketType, Scheme, HTTPOptions, Extra, Config).
-
-
-%%-------------------------------------------------------------------------
-
-ipv6(SocketType, Scheme, HTTPOptions, Extra, Config) ->
- %% Check if we are a IPv6 host
- tsp("ipv6 -> verify ipv6 support"),
- case inets_test_lib:has_ipv6_support(Config) of
- {ok, Addr} ->
- tsp("ipv6 -> ipv6 supported: ~p", [Addr]),
- {DummyServerPid, Port} = dummy_server(SocketType, ipv6, Extra),
- Profile = ?config(profile, Config),
- URL =
- Scheme ++
- "://[" ++ http_transport:ipv6_name(Addr) ++ "]:" ++
- integer_to_list(Port) ++ "/foobar.html",
- tsp("ipv6 -> issue request with: "
- "~n URL: ~p"
- "~n HTTPOptions: ~p", [URL, HTTPOptions]),
- case httpc:request(get, {URL, []}, HTTPOptions, [], Profile) of
- {ok, {{_,200,_}, [_ | _], [_|_]}} ->
- tsp("ipv6 -> expected result"),
- DummyServerPid ! stop,
- ok;
- {ok, Unexpected} ->
- tsp("ipv6 -> unexpected result: "
- "~n ~p", [Unexpected]),
- DummyServerPid ! stop,
- tsf({unexpected_result, Unexpected});
- {error, Reason} ->
- tsp("ipv6 -> error: "
- "~n Reason: ~p", [Reason]),
- DummyServerPid ! stop,
- tsf(Reason)
- end,
- ok;
- _ ->
- tsp("ipv6 -> ipv6 not supported"),
- skip("Host does not support IPv6")
- end.
-
-
-%%-------------------------------------------------------------------------
-
-headers_as_is(doc) ->
- ["Test the option headers_as_is"];
-headers_as_is(suite) ->
- [];
-headers_as_is(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_|_], [_|_]}} =
- httpc:request(get, {URL, [{"Host", "localhost"},{"Te", ""}]},
- [], [{headers_as_is, true}]),
-
- {ok, {{_,400,_}, [_|_], [_|_]}} =
- httpc:request(get, {URL, [{"Te", ""}]},[], [{headers_as_is, true}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-selecting_session(doc) ->
- ["Test selection of sessions - OTP-9847"];
-selecting_session(suite) ->
- [];
-selecting_session(Config) when is_list(Config) ->
- tsp("selecting_session -> entry with"
- "~n Config: ~p", [Config]),
-
- tsp("selecting_session -> set ipfamily to inet"),
- ok = httpc:set_options([{ipfamily, inet}]),
-
- tsp("selecting_session -> start server"),
- {ServerPid, Port} = otp_9847_server(),
-
- PortStr = integer_to_list(Port),
- URL = ?URL_START ++ PortStr ++ "/index.html",
-
- tsp("selecting_session -> issue the first batch (three) requests"),
- lists:foreach(fun(P) ->
- tsp("selecting_session:fun1 -> "
- "send stop request to ~p", [P]),
- P ! stop
- end,
- reqs(URL, ServerPid, 3, 3, false)),
- tsp("selecting_session -> sleep some (1) to make sure nothing lingers"),
- ?SLEEP(5000),
- tsp("selecting_session -> "
- "instruct the server to reply to the first request"),
- ServerPid ! {answer, true},
- receive
- {answer, true} ->
- tsp("selecting_session -> "
- "received ack from server to reply to the first request"),
- ok
- end,
- tsp("selecting_session -> issue the second batch (four) requests"),
- lists:foreach(fun(P) ->
- tsp("selecting_session:fun2 -> "
- "send stop request to ~p", [P]),
- P ! stop
- end,
- reqs(URL, ServerPid, 4, 1, true)),
- tsp("selecting_session -> sleep some (2) to make sure nothing lingers"),
- ?SLEEP(5000),
-
- tsp("selecting_session -> stop server"),
- ServerPid ! stop,
- tsp("selecting_session -> set ipfamily (back) to inet6fb4"),
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- tsp("selecting_session -> done"),
- ok.
-
-reqs(URL, ServerPid, NumReqs, NumHandlers, InitialSync) ->
- tsp("reqs -> entry with"
- "~n URL: ~p"
- "~n ServerPid: ~w"
- "~n NumReqs: ~w"
- "~n NumHandlers: ~w"
- "~n InitialSync: ~w",
- [URL, ServerPid, NumReqs, NumHandlers, InitialSync]),
- Handlers = reqs2(URL, NumReqs, [], InitialSync),
- tsp("reqs -> "
- "~n Handlers: ~w", [Handlers]),
- case length(Handlers) of
- NumHandlers ->
- tsp("reqs -> "
- "~n NumHandlers: ~w", [NumHandlers]),
- ServerPid ! num_handlers,
- receive
- {num_handlers, NumHandlers} ->
- tsp("reqs -> received num_handlers with"
- "~n NumHandlers: ~w", [NumHandlers]),
- Handlers;
- {num_handlers, WrongNumHandlers} ->
- tsp("reqs -> received num_handlers with"
- "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
- exit({wrong_num_handlers1, WrongNumHandlers, NumHandlers})
- end;
- WrongNumHandlers ->
- tsp("reqs -> "
- "~n WrongNumHandlers: ~w", [WrongNumHandlers]),
- exit({wrong_num_handlers2, WrongNumHandlers, NumHandlers})
- end.
-
-
-reqs2(_URL, 0, Acc, _Sync) ->
- lists:reverse(Acc);
-reqs2(URL, Num, Acc, Sync) ->
- tsp("reqs2 -> entry with"
- "~n Num: ~w"
- "~n Sync: ~w", [Num, Sync]),
- case httpc:request(get, {URL, []}, [], [{sync, Sync}]) of
- {ok, _Reply} ->
- tsp("reqs2 -> successful request: ~p", [_Reply]),
- receive
- {handler, Handler, _Manager} ->
- %% This is when a new handler is created
- tsp("reqs2 -> received handler: ~p", [Handler]),
- case lists:member(Handler, Acc) of
- true ->
- tsp("reqs2 -> duplicate handler"),
- exit({duplicate_handler, Handler, Num, Acc});
- false ->
- tsp("reqs2 -> wait for data ack"),
- receive
- {data_received, Handler} ->
- tsp("reqs2 -> "
- "received data ack from ~p", [Handler]),
- case Sync of
- true ->
- reqs2(URL, Num-1, [Handler|Acc],
- false);
- false ->
- reqs2(URL, Num-1, [Handler|Acc],
- Sync)
- end
- end
- end;
-
- {data_received, Handler} ->
- tsp("reqs2 -> "
- "received data ack from ~p", [Handler]),
- reqs2(URL, Num-1, Acc, false)
-
- end;
-
- {error, Reason} ->
- tsp("reqs2 -> request ~w failed: ~p", [Num, Reason]),
- exit({request_failed, Reason, Num, Acc})
- end.
-
-otp_9847_server() ->
- TC = self(),
- Pid = spawn_link(fun() -> otp_9847_server_init(TC) end),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-otp_9847_server_init(TC) ->
- tsp("otp_9847_server_init -> entry with"
- "~n TC: ~p", [TC]),
- {ok, ListenSocket} =
- gen_tcp:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}]),
- tsp("otp_9847_server_init -> listen socket created: "
- "~n ListenSocket: ~p", [ListenSocket]),
- {ok, Port} = inet:port(ListenSocket),
- tsp("otp_9847_server_init -> Port: ~p", [Port]),
- TC ! {port, Port},
- otp_9847_server_main(TC, ListenSocket, false, []).
-
-otp_9847_server_main(TC, ListenSocket, Answer, Handlers) ->
- tsp("otp_9847_server_main -> entry with"
- "~n TC: ~p"
- "~n ListenSocket: ~p"
- "~n Answer: ~p"
- "~n Handlers: ~p", [TC, ListenSocket, Answer, Handlers]),
- case gen_tcp:accept(ListenSocket, 1000) of
- {ok, Sock} ->
- tsp("otp_9847_server_main -> accepted"
- "~n Sock: ~p", [Sock]),
- {Handler, Mon, Port} = otp_9847_handler(TC, Sock, Answer),
- tsp("otp_9847_server_main -> handler ~p created for ~w",
- [Handler, Port]),
- gen_tcp:controlling_process(Sock, Handler),
- tsp("otp_9847_server_main -> control transfer"),
- Handler ! owner,
- tsp("otp_9847_server_main -> "
- "handler ~p informed of owner transfer", [Handler]),
- TC ! {handler, Handler, self()},
- tsp("otp_9847_server_main -> "
- "TC ~p informed of handler ~p", [TC, Handler]),
- otp_9847_server_main(TC, ListenSocket, Answer,
- [{Handler, Mon, Sock, Port}|Handlers]);
-
- {error, timeout} ->
- tsp("otp_9847_server_main -> timeout"),
- receive
- {answer, true} ->
- tsp("otp_9847_server_main -> received answer request"),
- TC ! {answer, true},
- otp_9847_server_main(TC, ListenSocket, true, Handlers);
-
- {'DOWN', _Mon, process, Pid, _Reason} ->
- %% Could be one of the handlers
- tsp("otp_9847_server_main -> received DOWN for ~p", [Pid]),
- otp_9847_server_main(TC, ListenSocket, Answer,
- lists:keydelete(Pid, 1, Handlers));
-
- num_handlers ->
- tsp("otp_9847_server_main -> "
- "received request for number of handlers (~w)",
- [length(Handlers)]),
- TC ! {num_handlers, length(Handlers)},
- otp_9847_server_main(TC, ListenSocket, Answer, Handlers);
-
- stop ->
- tsp("otp_9847_server_main -> received stop request"),
- %% Stop all handlers (just in case)
- Pids = [Handler || {Handler, _, _} <- Handlers],
- lists:foreach(fun(Pid) -> Pid ! stop end, Pids),
- exit(normal);
-
- Any ->
- tsp("otp_9847_server_main -> received"
- "~n Any: ~p", [Any]),
- exit({crap, Any})
-
- after 0 ->
- tsp("otp_9847_server_main -> nothing in queue"),
- otp_9847_server_main(TC, ListenSocket, Answer, Handlers)
- end;
-
- Error ->
- exit(Error)
- end.
-
-
-otp_9847_handler(TC, Sock, Answer) ->
- tsp("otp_9847_handler -> entry with"
- "~n TC: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p", [TC, Sock, Answer]),
- Self = self(),
- {Pid, Mon} =
- spawn_opt(fun() ->
- otp_9847_handler_init(TC, Self, Sock, Answer)
- end,
- [monitor]),
- receive
- {port, Port} ->
- tsp("otp_9847_handler -> received port message (from ~p)"
- "~n Port: ~p", [Pid, Port]),
- {Pid, Mon, Port}
- end.
-
-
-otp_9847_handler_init(TC, Server, Sock, Answer) ->
- tsp("otp_9847_handler_init -> entry with"
- "~n TC: ~p"
- "~n Server: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p", [TC, Server, Sock, Answer]),
- {ok, Port} = inet:port(Sock),
- Server ! {port, Port},
- receive
- owner ->
- tsp("otp_9847_handler_init -> "
- "received owner message - activate socket"),
- inet:setopts(Sock, [{active, true}]),
- otp_9847_handler_main(TC, Server, Sock, Answer, [?HTTP_MAX_HEADER_SIZE])
- end.
-
-otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs) ->
- tsp("otp_9847_handler_main -> entry with"
- "~n TC: ~p"
- "~n Server: ~p"
- "~n Sock: ~p"
- "~n Answer: ~p"
- "~n ParseArgs: ~p", [TC, Server, Sock, Answer, ParseArgs]),
- receive
- stop ->
- tsp("otp_9847_handler_main -> received stop request"),
- exit(normal);
-
- {tcp, Sock, _Data} when Answer =:= false ->
- tsp("otp_9847_handler_main -> received tcp data - no answer"),
- TC ! {data_received, self()},
- inet:setopts(Sock, [{active, true}]),
- %% Ignore all data
- otp_9847_handler_main(TC, Server, Sock, Answer, ParseArgs);
-
- {tcp, Sock, Data} when Answer =:= true ->
- tsp("otp_9847_handler_main -> received tcp data - answer"),
- TC ! {data_received, self()},
- inet:setopts(Sock, [{active, true}]),
- NewParseArgs = otp_9847_handler_request(Sock, [Data|ParseArgs]),
- otp_9847_handler_main(TC, Server, Sock, Answer, NewParseArgs);
-
- {tcp_closed, Sock} ->
- tsp("otp_9847_handler_main -> received tcp socket closed"),
- exit(normal);
-
- {tcp_error, Sock, Reason} ->
- tsp("otp_9847_handler_main -> socket error: ~p", [Reason]),
- (catch gen_tcp:close(Sock)),
- exit(normal)
-
- %% after 30000 ->
- %% gen_tcp:close(Sock),
- %% exit(normal)
- end.
-
-otp_9847_handler_request(Sock, Args) ->
- Msg =
- case httpd_request:parse(Args) of
- {ok, {_, "/index.html" = _RelUrl, _, _, _}} ->
- B =
- "<HTML><BODY>" ++
- "...some body part..." ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
- end,
- gen_tcp:send(Sock, Msg),
- [?HTTP_MAX_HEADER_SIZE].
-
-
-
-%%-------------------------------------------------------------------------
-
-options(doc) ->
- ["Test the option parameters."];
-options(suite) ->
- [];
-options(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- {ok, {{_,200,_}, [_ | _], Bin}}
- = httpc:request(get, {URL, []}, [{foo, bar}],
- %% Ignore unknown options
- [{body_format, binary}, {foo, bar}]),
-
- true = is_binary(Bin),
- {ok, {200, [_|_]}}
- = httpc:request(get, {URL, []}, [{timeout, infinity}],
- [{full_result, false}]);
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-
-http_invalid_http(doc) ->
- ["Test parse error"];
-http_invalid_http(suite) ->
- [];
-http_invalid_http(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/invalid_http.html",
-
- {error, {could_not_parse_as_http, _} = Reason} =
- httpc:request(get, {URL, []}, [], []),
-
- test_server:format("Parse error: ~p ~n", [Reason]),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
--define(GOOGLE, "www.google.com").
-
-hexed_query_otp_6191(doc) ->
- [];
-hexed_query_otp_6191(suite) ->
- [];
-hexed_query_otp_6191(Config) when is_list(Config) ->
- Google = ?GOOGLE,
- GoogleSearch = "http://" ++ Google ++ "/search",
- Search1 = "?hl=en&q=a%D1%85%D1%83%D0%B9&btnG=Google+Search",
- URI1 = GoogleSearch ++ Search1,
- Search2 = "?hl=en&q=%25%25",
- URI2 = GoogleSearch ++ Search2,
- Search3 = "?hl=en&q=%foo",
- URI3 = GoogleSearch ++ Search3,
-
- Verify1 =
- fun({http, [], ?GOOGLE, 80, "/search", _}) -> ok;
- (_) -> error
- end,
- Verify2 = Verify1,
- Verify3 = Verify1,
- verify_uri(URI1, Verify1),
- verify_uri(URI2, Verify2),
- verify_uri(URI3, Verify3),
- ok.
-
-verify_uri(URI, Verify) ->
- case http_uri:parse(URI) of
- {ok, ParsedURI} ->
- case Verify(ParsedURI) of
- ok ->
- ok;
- error ->
- Reason = {unexpected_parse_result, URI, ParsedURI},
- ERROR = {error, Reason},
- throw(ERROR)
- end;
- {error, _} = ERROR ->
- throw(ERROR)
- end.
-
-
-%%-------------------------------------------------------------------------
-
-empty_body_otp_6243(doc) ->
- ["An empty body was not returned directly. There was a delay for several"
- "seconds."];
-empty_body_otp_6243(suite) ->
- [];
-empty_body_otp_6243(Config) when is_list(Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/empty.html",
- {ok, {{_,200,_}, [_ | _], []}} =
- httpc:request(get, {URL, []}, [{timeout, 500}], []).
-
-
-%%-------------------------------------------------------------------------
-
-transfer_encoding_otp_6807(doc) ->
- ["Transfer encoding is case insensitive"];
-transfer_encoding_otp_6807(suite) ->
- [];
-transfer_encoding_otp_6807(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/capital_transfer_encoding.html",
- {ok, {{_,200,_}, [_|_], [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-empty_response_header_otp_6830(doc) ->
- ["Test the case that the HTTP server does not send any headers"];
-empty_response_header_otp_6830(suite) ->
- [];
-empty_response_header_otp_6830(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/no_headers.html",
- {ok, {{_,200,_}, [], [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-no_content_204_otp_6982(doc) ->
- ["Test the case that the HTTP 204 no content header"];
-no_content_204_otp_6982(suite) ->
- [];
-no_content_204_otp_6982(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/no_content.html",
- {ok, {{_,204,_}, [], []}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-missing_CR_otp_7304(doc) ->
- ["Test the case that the HTTP server uses only LF instead of CRLF"
- "as delimitor"];
-missing_CR_otp_7304(suite) ->
- [];
-missing_CR_otp_7304(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/missing_CR.html",
- {ok, {{_,200,_}, _, [_ | _]}} = httpc:request(URL),
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-otp_7883_1(doc) ->
- ["OTP-7883-sync"];
-otp_7883_1(suite) ->
- [];
-otp_7883_1(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
-
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
- {error, socket_closed_remotely} = httpc:request(URL),
- DummyServerPid ! stop,
-
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-otp_7883_2(doc) ->
- ["OTP-7883-async"];
-otp_7883_2(suite) ->
- [];
-otp_7883_2(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipfamily, inet}]),
-
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++ "/just_close.html",
- Method = get,
- Request = {URL, []},
- HttpOptions = [],
- Options = [{sync, false}],
- Profile = httpc:default_profile(),
- {ok, RequestId} =
- httpc:request(Method, Request, HttpOptions, Options, Profile),
- ok =
- receive
- {http, {RequestId, {error, socket_closed_remotely}}} ->
- ok
- end,
- DummyServerPid ! stop,
-
- ok = httpc:set_options([{ipfamily, inet6fb4}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-
-otp_8154_1(doc) ->
- ["OTP-8154"];
-otp_8154_1(suite) ->
- [];
-otp_8154_1(Config) when is_list(Config) ->
- start_inets(),
- ReqSeqNumServer = start_sequence_number_server(),
- RespSeqNumServer = start_sequence_number_server(),
- {ok, Server, Port} = start_slow_server(RespSeqNumServer),
- Clients = run_clients(105, Port, ReqSeqNumServer),
- %% ok = wait_for_clients(Clients),
- ok = wait4clients(Clients, timer:minutes(3)),
- Server ! shutdown,
- RespSeqNumServer ! shutdown,
- ReqSeqNumServer ! shutdown,
- ok.
-
-start_inets() ->
- inets:start(),
- ok.
-
-
-%% -----------------------------------------------------
-%% A sequence number handler
-%% The purpose is to be able to pair requests with responses.
-
-start_sequence_number_server() ->
- proc_lib:spawn(fun() -> loop_sequence_number(1) end).
-
-loop_sequence_number(N) ->
- receive
- shutdown ->
- ok;
- {From, get_next} ->
- From ! {next_is, N},
- loop_sequence_number(N + 1)
- end.
-
-get_next_sequence_number(SeqNumServer) ->
- SeqNumServer ! {self(), get_next},
- receive {next_is, N} -> N end.
-
-%% -----------------------------------------------------
-%% Client part
-%% Sends requests randomly parallel
-
-run_clients(NumClients, ServerPort, SeqNumServer) ->
- io:format("start clients when"
- "~n NumClients: ~w"
- "~n ServerPort: ~w"
- "~n SeqNumServer: ~w"
- "~n", [NumClients, ServerPort, SeqNumServer]),
- set_random_seed(),
- lists:map(
- fun(Id) ->
- io:format("starting client ~w~n", [Id]),
- Req = f("req~3..0w", [get_next_sequence_number(SeqNumServer)]),
- Url = f(?URL_START ++ "~w/~s", [ServerPort, Req]),
- Pid = proc_lib:spawn(
- fun() ->
- io:format("[~w] client started - "
- "issue request~n", [Id]),
- case httpc:request(Url) of
- {ok, {{_,200,_}, _, Resp}} ->
- io:format("[~w] 200 response: "
- "~p~n", [Id, Resp]),
- case lists:prefix(Req++"->", Resp) of
- true -> exit(normal);
- false -> exit({bad_resp,Req,Resp})
- end;
- {ok, {{_,EC,Reason},_,Resp}} ->
- io:format("[~w] ~w response: "
- "~s~n~s~n",
- [Id, EC, Reason, Resp]),
- exit({bad_resp,Req,Resp});
- Crap ->
- io:format("[~w] bad response: ~p",
- [Id, Crap]),
- exit({bad_resp, Req, Crap})
- end
- end),
- MRef = erlang:monitor(process, Pid),
- timer:sleep(10 + random:uniform(1334)),
- {Id, Pid, MRef}
-
- end,
- lists:seq(1, NumClients)).
-
-%% wait_for_clients(Clients) ->
-%% lists:foreach(
-%% fun({Id, Pid, MRef}) ->
-%% io:format("waiting for client ~w termination~n", [Id]),
-%% receive
-%% {'DOWN', MRef, process, Pid, normal} ->
-%% io:format("waiting for clients: "
-%% "normal exit from ~w (~p)~n",
-%% [Id, Pid]),
-%% ok;
-%% {'DOWN', MRef, process, Pid, Reason} ->
-%% io:format("waiting for clients: "
-%% "unexpected exit from ~w (~p):"
-%% "~n Reason: ~p"
-%% "~n", [Id, Pid, Reason]),
-%% erlang:error(Reason)
-%% end
-%% end,
-%% Clients).
-
-
-wait4clients([], _Timeout) ->
- ok;
-wait4clients(Clients, Timeout) when Timeout > 0 ->
- io:format("wait4clients -> entry with"
- "~n length(Clients): ~w"
- "~n Timeout: ~w"
- "~n", [length(Clients), Timeout]),
- T = t(),
- receive
- {'DOWN', _MRef, process, Pid, normal} ->
- case lists:keysearch(Pid, 2, Clients) of
- {value, {Id, _, _}} ->
- io:format("receive normal exit message "
- "from client ~p (~p)", [Id, Pid]),
- NewClients =
- lists:keydelete(Id, 1, Clients),
- wait4clients(NewClients,
- Timeout - (t() - T));
- false ->
- io:format("receive normal exit message "
- "from unknown process: ~p", [Pid]),
- wait4clients(Clients, Timeout - (t() - T))
- end;
-
- {'DOWN', _MRef, process, Pid, Reason} ->
- case lists:keysearch(Pid, 2, Clients) of
- {value, {Id, _, _}} ->
- io:format("receive bad exit message "
- "from client ~p (~p):"
- "~n ~p", [Id, Pid, Reason]),
- erlang:error({bad_client_termination, Id, Reason});
- false ->
- io:format("receive normal exit message "
- "from unknown process: ~p", [Pid]),
- wait4clients(Clients, Timeout - (t() - T))
- end
-
- after Timeout ->
- erlang:error({client_timeout, Clients})
- end;
-wait4clients(Clients, _) ->
- erlang:error({client_timeout, Clients}).
-
-
-%% Time in milli seconds
-t() ->
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000).
-
-
-%% -----------------------------------------------------
-%% Webserver part:
-%% Implements a web server that sends responses one character
-%% at a time, with random delays between the characters.
-
-start_slow_server(SeqNumServer) ->
- io:format("start slow server when"
- "~n SeqNumServer: ~w"
- "~n", [SeqNumServer]),
- proc_lib:start(
- erlang, apply, [fun() -> init_slow_server(SeqNumServer) end, []]).
-
-init_slow_server(SeqNumServer) ->
- io:format("[webserver ~w] init slow server"
- "~n", [SeqNumServer]),
- {ok, LSock} = gen_tcp:listen(0, [binary, {packet,0}, {active,true},
- {backlog, 100}]),
- io:format("[webserver ~w] LSock: ~p"
- "~n", [SeqNumServer, LSock]),
- {ok, {_IP, Port}} = inet:sockname(LSock),
- io:format("[webserver ~w] Port: ~w"
- "~n", [SeqNumServer, Port]),
- proc_lib:init_ack({ok, self(), Port}),
- loop_slow_server(LSock, SeqNumServer).
-
-loop_slow_server(LSock, SeqNumServer) ->
- io:format("[webserver ~w] entry with"
- "~n LSock: ~p"
- "~n", [SeqNumServer, LSock]),
- Master = self(),
- Acceptor = proc_lib:spawn(
- fun() -> client_handler(Master, LSock, SeqNumServer) end),
- io:format("[webserver ~w] acceptor started"
- "~n Acceptor: ~p"
- "~n", [SeqNumServer, Acceptor]),
- receive
- {accepted, Acceptor} ->
- io:format("[webserver ~w] accepted"
- "~n", [SeqNumServer]),
- loop_slow_server(LSock, SeqNumServer);
- shutdown ->
- gen_tcp:close(LSock),
- exit(Acceptor, kill)
- end.
-
-
-%% Handle one client connection
-client_handler(Master, LSock, SeqNumServer) ->
- io:format("[acceptor ~w] await accept"
- "~n", [SeqNumServer]),
- {ok, CSock} = gen_tcp:accept(LSock),
- io:format("[acceptor ~w] accepted"
- "~n CSock: ~p"
- "~n", [SeqNumServer, CSock]),
- Master ! {accepted, self()},
- set_random_seed(),
- loop_client(1, CSock, SeqNumServer).
-
-loop_client(N, CSock, SeqNumServer) ->
- %% Await request, don't bother parsing it too much,
- %% assuming the entire request arrives in one packet.
- io:format("[acceptor ~w] await request"
- "~n N: ~p"
- "~n", [SeqNumServer, N]),
- receive
- {tcp, CSock, Req} ->
- ReqNum = parse_req_num(Req),
- RespSeqNum = get_next_sequence_number(SeqNumServer),
- Response = f("~s->resp~3..0w/~2..0w", [ReqNum, RespSeqNum, N]),
- Txt = f("Slow server (~p) got ~p, answering with ~p",
- [self(), Req, Response]),
- io:format("~s...~n", [Txt]),
- slowly_send_response(CSock, Response),
- case parse_connection_type(Req) of
- keep_alive ->
- io:format("~s...done~n", [Txt]),
- loop_client(N+1, CSock, SeqNumServer);
- close ->
- io:format("~s...done (closing)~n", [Txt]),
- gen_tcp:close(CSock)
- end
- end.
-
-slowly_send_response(CSock, Answer) ->
- Response = f("HTTP/1.1 200 OK\r\nContent-Length: ~w\r\n\r\n~s",
- [length(Answer), Answer]),
- lists:foreach(
- fun(Char) ->
- timer:sleep(random:uniform(500)),
- gen_tcp:send(CSock, <<Char>>)
- end,
- Response).
-
-parse_req_num(Request) ->
- Opts = [caseless,{capture,all_but_first,list}],
- {match, [ReqNum]} = re:run(Request, "GET /(.*) HTTP", Opts),
- ReqNum.
-
-parse_connection_type(Request) ->
- Opts = [caseless,{capture,all_but_first,list}],
- {match,[CType]} = re:run(Request, "connection: *(keep-alive|close)", Opts),
- case string:to_lower(CType) of
- "close" -> close;
- "keep-alive" -> keep_alive
- end.
-
-
-set_random_seed() ->
- {_, _, Micros} = now(),
- A = erlang:phash2([make_ref(), self(), Micros]),
- random:seed(A, A, A).
-
-f(F, A) -> lists:flatten(io_lib:format(F,A)).
-
-
-
-
-%%-------------------------------------------------------------------------
-
-
-
-otp_8106_pid(doc) ->
- ["OTP-8106 - deliver reply info using \"other\" pid"];
-otp_8106_pid(suite) ->
- [];
-otp_8106_pid(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(pid),
- Receiver = ReceiverPid,
-
- otp8106(ReceiverPid, Receiver, Config),
-
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-otp_8106_fun(doc) ->
- ["OTP-8106 - deliver reply info using fun"];
-otp_8106_fun(suite) ->
- [];
-otp_8106_fun(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(function),
- Receiver = otp_8106_deliver_fun(ReceiverPid),
-
- otp8106(ReceiverPid, Receiver, Config),
-
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-otp_8106_mfa(doc) ->
- ["OTP-8106 - deliver reply info using mfa callback"];
-otp_8106_mfa(suite) ->
- [];
-otp_8106_mfa(Config) when is_list(Config) ->
- case ?config(local_server, Config) of
- ok ->
- ReceiverPid = create_receiver(mfa),
- Receiver = {?MODULE, otp_8106_deliver, [mfa, ReceiverPid]},
-
- otp8106(ReceiverPid, Receiver, Config),
-
- stop_receiver(ReceiverPid),
-
- ok;
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
- otp8106(ReceiverPid, Receiver, Config) ->
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HTTPOptions = [],
- Options = [{sync, false}, {receiver, Receiver}],
-
- {ok, RequestId} =
- httpc:request(get, Request, HTTPOptions, Options),
-
- Body =
- receive
- {reply, ReceiverPid, {RequestId, {{_, 200, _}, _, B}}} ->
- B;
- {reply, ReceiverPid, Msg} ->
- tsf(Msg);
- {bad_reply, ReceiverPid, Msg} ->
- tsf(Msg)
- end,
-
- inets_test_lib:check_body(binary_to_list(Body)),
- ok.
-
-
-create_receiver(Type) ->
- Parent = self(),
- Receiver = fun() -> receiver(Type, Parent) end,
- spawn_link(Receiver).
-
-stop_receiver(Pid) ->
- Pid ! {stop, self()}.
-
-receiver(Type, Parent) ->
- receive
- {stop, Parent} ->
- exit(normal);
-
- {http, ReplyInfo} when (Type =:= pid) ->
- Parent ! {reply, self(), ReplyInfo},
- receiver(Type, Parent);
-
- {Type, ReplyInfo} ->
- Parent ! {reply, self(), ReplyInfo},
- receiver(Type, Parent);
-
- Crap ->
- Parent ! {reply, self(), {bad_reply, Crap}},
- receiver(Type, Parent)
- end.
-
-
-otp_8106_deliver_fun(ReceiverPid) ->
- fun(ReplyInfo) -> otp_8106_deliver(ReplyInfo, function, ReceiverPid) end.
-
-otp_8106_deliver(ReplyInfo, Type, ReceiverPid) ->
- ReceiverPid ! {Type, ReplyInfo},
- ok.
-
-
-
-%%-------------------------------------------------------------------------
-
-otp_8056(doc) ->
- "OTP-8056";
-otp_8056(suite) ->
- [];
-otp_8056(Config) when is_list(Config) ->
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- HTTPOptions = [],
- Options1 = [{sync, true}, {stream, {self, once}}],
- Options2 = [{sync, true}, {stream, self}],
- {error, streaming_error} = httpc:request(Method, Request,
- HTTPOptions, Options1),
- tsp("request 1 failed as expected"),
- {error, streaming_error} = httpc:request(Method, Request,
- HTTPOptions, Options2),
- tsp("request 2 failed as expected"),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-otp_8352(doc) ->
- "OTP-8352";
-otp_8352(suite) ->
- [];
-otp_8352(Config) when is_list(Config) ->
- tsp("otp_8352 -> entry with"
- "~n Config: ~p", [Config]),
- case ?config(local_server, Config) of
- ok ->
- tsp("local-server running"),
-
- tsp("initial profile info(1): ~p", [httpc:info()]),
-
- MaxSessions = 5,
- MaxKeepAlive = 10,
- KeepAliveTimeout = timer:minutes(2),
- ConnOptions = [{max_sessions, MaxSessions},
- {max_keep_alive_length, MaxKeepAlive},
- {keep_alive_timeout, KeepAliveTimeout}],
- httpc:set_options(ConnOptions),
-
- Method = get,
- Port = ?config(local_port, Config),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Request = {URL, []},
- Timeout = timer:seconds(1),
- ConnTimeout = Timeout + timer:seconds(1),
- HttpOptions1 = [{timeout, Timeout}, {connect_timeout, ConnTimeout}],
- Options1 = [{socket_opts, [{tos, 87},
- {recbuf, 16#FFFF},
- {sndbuf, 16#FFFF}]}],
- case httpc:request(Method, Request, HttpOptions1, Options1) of
- {ok, {{_,200,_}, [_ | _], ReplyBody1 = [_ | _]}} ->
- %% equivaliant to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(ReplyBody1);
- {ok, UnexpectedReply1} ->
- tsf({unexpected_reply, UnexpectedReply1});
- {error, _} = Error1 ->
- tsf({bad_reply, Error1})
- end,
-
- tsp("profile info (2): ~p", [httpc:info()]),
-
- HttpOptions2 = [],
- Options2 = [{socket_opts, [{tos, 84},
- {recbuf, 32#1FFFF},
- {sndbuf, 32#1FFFF}]}],
- case httpc:request(Method, Request, HttpOptions2, Options2) of
- {ok, {{_,200,_}, [_ | _], ReplyBody2 = [_ | _]}} ->
- %% equivaliant to httpc:request(get, {URL, []}, [], []),
- inets_test_lib:check_body(ReplyBody2);
- {ok, UnexpectedReply2} ->
- tsf({unexpected_reply, UnexpectedReply2});
- {error, _} = Error2 ->
- tsf({bad_reply, Error2})
- end,
- tsp("profile info (3): ~p", [httpc:info()]),
- ok;
-
- _ ->
- skip("Failed to start local http-server")
- end.
-
-
-%%-------------------------------------------------------------------------
-
-otp_8371(doc) ->
- ["OTP-8371"];
-otp_8371(suite) ->
- [];
-otp_8371(Config) when is_list(Config) ->
- ok = httpc:set_options([{ipv6, disabled}]), % also test the old option
- {DummyServerPid, Port} = dummy_server(ipv4),
-
- URL = ?URL_START ++ integer_to_list(Port) ++
- "/ensure_host_header_with_port.html",
-
- case httpc:request(get, {URL, []}, [], []) of
- {ok, Result} ->
- case Result of
- {{_, 200, _}, _Headers, Body} ->
- tsp("expected response with"
- "~n Body: ~p", [Body]),
- ok;
- {StatusLine, Headers, Body} ->
- tsp("expected response with"
- "~n StatusLine: ~p"
- "~n Headers: ~p"
- "~n Body: ~p", [StatusLine, Headers, Body]),
- tsf({unexpected_result,
- [{status_line, StatusLine},
- {headers, Headers},
- {body, Body}]});
- _ ->
- tsf({unexpected_result, Result})
- end;
- Error ->
- tsf({request_failed, Error})
- end,
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipv6, enabled}]),
- ok.
-
-
-%%-------------------------------------------------------------------------
-
-otp_8739(doc) ->
- ["OTP-8739"];
-otp_8739(suite) ->
- [];
-otp_8739(Config) when is_list(Config) ->
- {_DummyServerPid, Port} = otp_8739_dummy_server(),
- URL = ?URL_START ++ integer_to_list(Port) ++ "/dummy.html",
- Method = get,
- Request = {URL, []},
- HttpOptions = [{connect_timeout, 500}, {timeout, 1}],
- Options = [{sync, true}],
- case httpc:request(Method, Request, HttpOptions, Options) of
- {error, timeout} ->
- %% And now we check the size of the handler db
- Info = httpc:info(),
- tsp("Info: ~p", [Info]),
- {value, {handlers, Handlers}} =
- lists:keysearch(handlers, 1, Info),
- case Handlers of
- [] ->
- ok;
- _ ->
- tsf({unexpected_handlers, Handlers})
- end;
- Unexpected ->
- tsf({unexpected, Unexpected})
- end.
-
-
-otp_8739_dummy_server() ->
- Parent = self(),
- Pid = spawn_link(fun() -> otp_8739_dummy_server_init(Parent) end),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-otp_8739_dummy_server_init(Parent) ->
- {ok, ListenSocket} =
- gen_tcp:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}]),
- {ok, Port} = inet:port(ListenSocket),
- Parent ! {port, Port},
- otp_8739_dummy_server_main(Parent, ListenSocket).
-
-otp_8739_dummy_server_main(_Parent, ListenSocket) ->
- case gen_tcp:accept(ListenSocket) of
- {ok, Sock} ->
- %% Ignore the request, and simply wait for the socket to close
- receive
- {tcp_closed, Sock} ->
- (catch gen_tcp:close(ListenSocket)),
- exit(normal);
- {tcp_error, Sock, Reason} ->
- tsp("socket error: ~p", [Reason]),
- (catch gen_tcp:close(ListenSocket)),
- exit(normal)
- after 10000 ->
- %% Just in case
- (catch gen_tcp:close(Sock)),
- (catch gen_tcp:close(ListenSocket)),
- exit(timeout)
- end;
- Error ->
- exit(Error)
- end.
-
-
-%%-------------------------------------------------------------------------
-
-initial_server_connect(doc) ->
- ["If this test cases times out the init of httpc_handler process is"
- "blocking the manager/client process (implementation dependent which) but nither"
- "should be blocked."];
-initial_server_connect(suite) ->
- [];
-initial_server_connect(Config) when is_list(Config) ->
- DataDir = ?config(data_dir, Config),
- ok = httpc:set_options([{ipfamily, inet}]),
-
- CertFile = filename:join(DataDir, "ssl_server_cert.pem"),
- SSLOptions = [{certfile, CertFile}, {keyfile, CertFile}],
-
- {DummyServerPid, Port} = dummy_ssl_server_hang(self(), ipv4, SSLOptions),
-
- URL = ?SSL_URL_START ++ integer_to_list(Port) ++ "/index.html",
-
- httpc:request(get, {URL, []}, [{ssl,{essl,[]}}], [{sync, false}]),
-
- [{session_cookies,[]}] = httpc:which_cookies(),
-
- DummyServerPid ! stop,
- ok = httpc:set_options([{ipfamily, inet6fb4}]).
-
-%%--------------------------------------------------------------------
-%% Internal functions
-%%--------------------------------------------------------------------
-setup_server_dirs(ServerRoot, DocRoot, DataDir) ->
- ConfDir = filename:join(ServerRoot, "conf"),
- CgiDir = filename:join(ServerRoot, "cgi-bin"),
- ok = file:make_dir(ServerRoot),
- ok = file:make_dir(DocRoot),
- ok = file:make_dir(ConfDir),
- ok = file:make_dir(CgiDir),
-
- {ok, Files} = file:list_dir(DataDir),
-
- lists:foreach(fun(File) -> case lists:suffix(".html", File) of
- true ->
- inets_test_lib:copy_file(File,
- DataDir,
- DocRoot);
- false ->
- ok
- end
- end, Files),
-
- Cgi = case test_server:os_type() of
- {win32, _} ->
- "cgi_echo.exe";
- _ ->
- "cgi_echo"
- end,
-
- inets_test_lib:copy_file(Cgi, DataDir, CgiDir),
- inets_test_lib:copy_file("mime.types", DataDir, ConfDir).
-
-create_config(FileName, ComType, Port, PrivDir, ServerRoot, DocRoot,
- SSLDir) ->
- MaxHdrSz = io_lib:format("~p", [256]),
- MaxHdrAct = io_lib:format("~p", [close]),
- SSL =
- case ComType of
- ssl ->
- [cline(["SSLCertificateFile ",
- filename:join(SSLDir, "ssl_server_cert.pem")]),
- cline(["SSLCertificateKeyFile ",
- filename:join(SSLDir, "ssl_server_cert.pem")]),
- cline(["SSLVerifyClient 0"])];
- _ ->
- []
- end,
-
- Mod_order = "Modules mod_alias mod_auth mod_esi mod_actions mod_cgi"
- " mod_include mod_dir mod_get mod_head"
- " mod_log mod_disk_log mod_trace",
-
- %% BindAddress = "*|inet", % Force the use of IPv4
- BindAddress = "*", % This corresponds to using IpFamily inet6fb4
-
- HttpConfig = [
- cline(["BindAddress ", BindAddress]),
- cline(["Port ", integer_to_list(Port)]),
- cline(["ServerName ", "httpc_test"]),
- cline(["SocketType ", atom_to_list(ComType)]),
- cline([Mod_order]),
- cline(["ServerRoot ", ServerRoot]),
- cline(["DocumentRoot ", DocRoot]),
- cline(["MaxHeaderSize ",MaxHdrSz]),
- cline(["MaxHeaderAction ",MaxHdrAct]),
- cline(["DirectoryIndex ", "index.html "]),
- cline(["DefaultType ", "text/plain"]),
- cline(["ScriptAlias /cgi-bin/ ",
- filename:join(ServerRoot, "cgi-bin"), "/"]),
- SSL],
- ConfigFile = filename:join([PrivDir,FileName]),
- {ok, Fd} = file:open(ConfigFile, [write]),
- ok = file:write(Fd, lists:flatten(HttpConfig)),
- ok = file:close(Fd).
-
-cline(List) ->
- lists:flatten([List, "\r\n"]).
-
-receive_streamed_body(RequestId, Body) ->
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- receive_streamed_body(RequestId,
- <<Body/binary, BinBodyPart/binary>>);
- {http, {RequestId, stream_end, _Headers}} ->
- Body;
- {http, Msg} ->
- tsf(Msg)
- end.
-
-receive_streamed_body(RequestId, Body, Pid) ->
- httpc:stream_next(Pid),
- test_server:format("~p:receive_streamed_body -> requested next stream ~n", [?MODULE]),
- receive
- {http, {RequestId, stream, BinBodyPart}} ->
- receive_streamed_body(RequestId,
- <<Body/binary, BinBodyPart/binary>>,
- Pid);
- {http, {RequestId, stream_end, _Headers}} ->
- Body;
- {http, Msg} ->
- tsf(Msg)
- end.
-
-%% Perform a synchronous stop
-dummy_server_stop(Pid) ->
- Pid ! {stop, self()},
- receive
- {stopped, Pid} ->
- ok
- end.
-
-dummy_server(IpV) ->
- dummy_server(self(), ip_comm, IpV, []).
-
-dummy_server(SocketType, IpV, Extra) ->
- dummy_server(self(), SocketType, IpV, Extra).
-
-dummy_server(Caller, SocketType, IpV, Extra) ->
- Args = [Caller, SocketType, IpV, Extra],
- Pid = spawn(httpc_SUITE, dummy_server_init, Args),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-dummy_server_init(Caller, ip_comm, IpV, _) ->
- BaseOpts = [binary, {packet, 0}, {reuseaddr,true}, {active, false}],
- {ok, ListenSocket} =
- case IpV of
- ipv4 ->
- tsp("ip_comm ipv4 listen", []),
- gen_tcp:listen(0, [inet | BaseOpts]);
- ipv6 ->
- tsp("ip_comm ipv6 listen", []),
- gen_tcp:listen(0, [inet6 | BaseOpts])
- end,
- {ok, Port} = inet:port(ListenSocket),
- tsp("dummy_server_init(ip_comm) -> Port: ~p", [Port]),
- Caller ! {port, Port},
- dummy_ipcomm_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
- [], ListenSocket);
-dummy_server_init(Caller, essl, IpV, SSLOptions) ->
- BaseOpts = [{ssl_imp, new},
- {backlog, 128}, binary, {reuseaddr,true}, {active, false} |
- SSLOptions],
- dummy_ssl_server_init(Caller, BaseOpts, IpV).
-
-dummy_ssl_server_init(Caller, BaseOpts, IpV) ->
- {ok, ListenSocket} =
- case IpV of
- ipv4 ->
- tsp("dummy_ssl_server_init -> ssl ipv4 listen", []),
- ssl:listen(0, [inet | BaseOpts]);
- ipv6 ->
- tsp("dummy_ssl_server_init -> ssl ipv6 listen", []),
- ssl:listen(0, [inet6 | BaseOpts])
- end,
- tsp("dummy_ssl_server_init -> ListenSocket: ~p", [ListenSocket]),
- {ok, {_, Port}} = ssl:sockname(ListenSocket),
- tsp("dummy_ssl_server_init -> Port: ~p", [Port]),
- Caller ! {port, Port},
- dummy_ssl_server_loop({httpd_request, parse, [?HTTP_MAX_HEADER_SIZE]},
- [], ListenSocket).
-
-dummy_ipcomm_server_loop(MFA, Handlers, ListenSocket) ->
- receive
- stop ->
- tsp("dummy_ipcomm_server_loop -> stop handlers", []),
- lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
- {stop, From} ->
- tsp("dummy_ipcomm_server_loop -> "
- "stop command from ~p for handlers (~p)", [From, Handlers]),
- Stopper = fun(Handler) -> Handler ! stop end,
- lists:foreach(Stopper, Handlers),
- From ! {stopped, self()}
- after 0 ->
- tsp("dummy_ipcomm_server_loop -> await accept", []),
- {ok, Socket} = gen_tcp:accept(ListenSocket),
- tsp("dummy_ipcomm_server_loop -> accepted: ~p", [Socket]),
- HandlerPid = dummy_request_handler(MFA, Socket),
- tsp("dummy_icomm_server_loop -> handler created: ~p", [HandlerPid]),
- gen_tcp:controlling_process(Socket, HandlerPid),
- tsp("dummy_ipcomm_server_loop -> "
- "control transfered to handler", []),
- HandlerPid ! ipcomm_controller,
- tsp("dummy_ipcomm_server_loop -> "
- "handler informed about control transfer", []),
- dummy_ipcomm_server_loop(MFA, [HandlerPid | Handlers],
- ListenSocket)
- end.
-
-dummy_ssl_server_loop(MFA, Handlers, ListenSocket) ->
- receive
- stop ->
- tsp("dummy_ssl_server_loop -> stop handlers", []),
- lists:foreach(fun(Handler) -> Handler ! stop end, Handlers);
- {stop, From} ->
- tsp("dummy_ssl_server_loop -> "
- "stop command from ~p for handlers (~p)", [From, Handlers]),
- Stopper = fun(Handler) -> Handler ! stop end,
- lists:foreach(Stopper, Handlers),
- From ! {stopped, self()}
- after 0 ->
- tsp("dummy_ssl_server_loop -> await accept", []),
- {ok, Socket} = ssl:transport_accept(ListenSocket),
- tsp("dummy_ssl_server_loop -> accepted: ~p", [Socket]),
- HandlerPid = dummy_request_handler(MFA, Socket),
- tsp("dummy_ssl_server_loop -> handler created: ~p", [HandlerPid]),
- ssl:controlling_process(Socket, HandlerPid),
- tsp("dummy_ssl_server_loop -> control transfered to handler", []),
- HandlerPid ! ssl_controller,
- tsp("dummy_ssl_server_loop -> "
- "handler informed about control transfer", []),
- dummy_ssl_server_loop(MFA, [HandlerPid | Handlers],
- ListenSocket)
- end.
-
-dummy_request_handler(MFA, Socket) ->
- tsp("spawn request handler", []),
- spawn(httpc_SUITE, dummy_request_handler_init, [MFA, Socket]).
-
-dummy_request_handler_init(MFA, Socket) ->
- SockType =
- receive
- ipcomm_controller ->
- tsp("dummy_request_handler_init -> "
- "received ip_comm controller - activate", []),
- inet:setopts(Socket, [{active, true}]),
- ip_comm;
- ssl_controller ->
- tsp("dummy_request_handler_init -> "
- "received ssl controller - activate", []),
- ssl:setopts(Socket, [{active, true}]),
- ssl
- end,
- dummy_request_handler_loop(MFA, SockType, Socket).
-
-dummy_request_handler_loop({Module, Function, Args}, SockType, Socket) ->
- tsp("dummy_request_handler_loop -> entry with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
- receive
- {Proto, _, Data} when (Proto =:= tcp) orelse (Proto =:= ssl) ->
- tsp("dummy_request_handler_loop -> [~w] Data ~p", [Proto, Data]),
- case handle_request(Module, Function, [Data | Args], Socket, Proto) of
- stop when Proto =:= tcp ->
- gen_tcp:close(Socket);
- stop when Proto =:= ssl ->
- ssl:close(Socket);
- NewMFA ->
- dummy_request_handler_loop(NewMFA, SockType, Socket)
- end;
- stop when SockType =:= ip_comm ->
- gen_tcp:close(Socket);
- stop when SockType =:= ssl ->
- ssl:close(Socket)
- end.
-
-
-mk_close(tcp) -> fun(Sock) -> gen_tcp:close(Sock) end;
-mk_close(ssl) -> fun(Sock) -> ssl:close(Sock) end.
-
-mk_send(tcp) -> fun(Sock, Data) -> gen_tcp:send(Sock, Data) end;
-mk_send(ssl) -> fun(Sock, Data) -> ssl:send(Sock, Data) end.
-
-handle_request(Module, Function, Args, Socket, Proto) ->
- Close = mk_close(Proto),
- Send = mk_send(Proto),
- handle_request(Module, Function, Args, Socket, Close, Send).
-
-handle_request(Module, Function, Args, Socket, Close, Send) ->
- tsp("handle_request -> entry with"
- "~n Module: ~p"
- "~n Function: ~p"
- "~n Args: ~p", [Module, Function, Args]),
- case Module:Function(Args) of
- {ok, Result} ->
- tsp("handle_request -> ok"
- "~n Result: ~p", [Result]),
- case (catch handle_http_msg(Result, Socket, Close, Send)) of
- stop ->
- stop;
- <<>> ->
- tsp("handle_request -> empty data"),
- {httpd_request, parse, [[<<>>, ?HTTP_MAX_HEADER_SIZE]]};
- Data ->
- handle_request(httpd_request, parse,
- [Data |[?HTTP_MAX_HEADER_SIZE]], Socket,
- Close, Send)
- end;
- NewMFA ->
- tsp("handle_request -> "
- "~n NewMFA: ~p", [NewMFA]),
- NewMFA
- end.
-
-handle_http_msg({_, RelUri, _, {_, Headers}, Body}, Socket, Close, Send) ->
- tsp("handle_http_msg -> entry with: "
- "~n RelUri: ~p"
- "~n Headers: ~p"
- "~n Body: ~p", [RelUri, Headers, Body]),
- NextRequest =
- case RelUri of
- "/dummy_headers.html" ->
- <<>>;
- "/no_headers.html" ->
- stop;
- "/just_close.html" ->
- stop;
- _ ->
- ContentLength = content_length(Headers),
- case size(Body) - ContentLength of
- 0 ->
- <<>>;
- _ ->
- <<_BodyThisReq:ContentLength/binary,
- Next/binary>> = Body,
- Next
- end
- end,
-
- tsp("handle_http_msg -> NextRequest: ~p", [NextRequest]),
- case (catch ets:lookup(cookie, cookies)) of
- [{cookies, true}]->
- tsp("handle_http_msg -> check cookies ~p", []),
- check_cookie(Headers);
- _ ->
- ok
- end,
-
- DefaultResponse = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n\r\n"
- "<HTML><BODY>foobar</BODY></HTML>",
-
- Msg =
- case RelUri of
- "/just_close.html" ->
- close;
- "/no_content.html" ->
- "HTTP/1.0 204 No Content\r\n\r\n";
- "/no_headers.html" ->
- "HTTP/1.0 200 OK\r\n\r\nTEST";
- "/ensure_host_header_with_port.html" ->
- %% tsp("handle_http_msg -> validate host with port"),
- case ensure_host_header_with_port(Headers) of
- true ->
- B =
- "<HTML><BODY>" ++
- "host with port" ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B;
- false ->
- B =
- "<HTML><BODY>" ++
- "Internal Server Error - host without port" ++
- "</BODY></HTML>",
- Len = integer_to_list(length(B)),
- "HTTP/1.1 500 Internal Server Error\r\n" ++
- "Content-Length:" ++ Len ++ "\r\n\r\n" ++ B
- end;
- "/300.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 300 Multiple Choices\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:0\r\n\r\n";
- "/301.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 301 Moved Permanently\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/302.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 302 Found \r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/303.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 303 See Other \r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/307.html" ->
- NewUri = ?URL_START ++
- integer_to_list(?IP_PORT) ++ "/dummy.html",
- "HTTP/1.1 307 Temporary Rediect \r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:80\r\n\r\n" ++
- "<HTML><BODY><a href=" ++ NewUri ++
- ">New place</a></BODY></HTML>";
- "/500.html" ->
- "HTTP/1.1 500 Internal Server Error\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>";
- "/503.html" ->
- case ets:lookup(unavailable, 503) of
- [{503, unavailable}] ->
- ets:insert(unavailable, {503, available}),
- "HTTP/1.1 503 Service Unavailable\r\n" ++
- "Retry-After:5\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>";
- [{503, available}] ->
- DefaultResponse;
- [{503, long_unavailable}] ->
- "HTTP/1.1 503 Service Unavailable\r\n" ++
- "Retry-After:120\r\n" ++
- "Content-Length:47\r\n\r\n" ++
- "<HTML><BODY>Internal Server Error</BODY></HTML>"
- end;
- "/redirectloop.html" -> %% Create a potential endless loop!
- {ok, Port} = inet:port(Socket),
- NewUri = ?URL_START ++
- integer_to_list(Port) ++ "/redirectloop.html",
- "HTTP/1.1 300 Multiple Choices\r\n" ++
- "Location:" ++ NewUri ++ "\r\n" ++
- "Content-Length:0\r\n\r\n";
- "/userinfo.html" ->
- Challange = "HTTP/1.1 401 Unauthorized \r\n" ++
- "WWW-Authenticate:Basic" ++"\r\n" ++
- "Content-Length:0\r\n\r\n",
- case auth_header(Headers) of
- {ok, Value} ->
- handle_auth(Value, Challange, DefaultResponse);
- _ ->
- Challange
- end;
- "/dummy_headers.html" ->
- %% The client will only care about the Transfer-Encoding
- %% header the rest of these headers are left to the
- %% user to evaluate. This is not a valid response
- %% it only tests that the header handling code works.
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n" ++
- "Pragma:1#no-cache\r\n" ++
- "Via:1.0 fred, 1.1 nowhere.com (Apache/1.1)\r\n" ++
- "Warning:1#pseudonym foobar\r\n" ++
- "Vary:*\r\n" ++
- "Trailer:Other:inets_test\r\n" ++
- "Upgrade:HTTP/2.0\r\n" ++
- "Age:4711\r\n" ++
- "Transfer-Encoding:chunked\r\n" ++
- "Content-Encoding:foo\r\n" ++
- "Content-Language:en\r\n" ++
- "Content-Location:http://www.foobar.se\r\n" ++
- "Content-MD5:104528739076276072743283077410617235478\r\n"
- ++
- "Content-Range:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
- "Expires:Sat, 29 Oct 1994 19:43:31 GMT\r\n" ++
- "Proxy-Authenticate:#1Basic" ++
- "\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/capital_transfer_encoding.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Transfer-Encoding:Chunked\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket, http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/cookie.html" ->
- "HTTP/1.1 200 ok\r\n" ++
- "set-cookie:" ++ "test_cookie=true; path=/;" ++
- "max-age=60000\r\n" ++
- "Content-Length:32\r\n\r\n"++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/missing_crlf.html" ->
- "HTTP/1.1 200 ok" ++
- "Content-Length:32\r\n" ++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/wrong_statusline.html" ->
- "ok 200 HTTP/1.1\r\n\r\n" ++
- "Content-Length:32\r\n\r\n" ++
- "<HTML><BODY>foobar</BODY></HTML>";
- "/once_chunked.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Transfer-Encoding:Chunked\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, http_chunk:encode("<HTML><BODY>fo")),
- Send(Socket,
- http_chunk:encode("obar</BODY></HTML>")),
- http_chunk:encode_last();
- "/once.html" ->
- Head = "HTTP/1.1 200 ok\r\n" ++
- "Content-Length:32\r\n\r\n",
- Send(Socket, Head),
- Send(Socket, "<HTML><BODY>fo"),
- test_server:sleep(1000),
- Send(Socket, "ob"),
- test_server:sleep(1000),
- Send(Socket, "ar</BODY></HTML>");
- "/invalid_http.html" ->
- "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
- "Transfer-Encoding:chunked\r\n\r\n";
- "/missing_reason_phrase.html" ->
- "HTTP/1.1 200\r\n" ++
- "Content-Length: 32\r\n\r\n"
- "<HTML><BODY>foobar</BODY></HTML>";
- "/missing_CR.html" ->
- "HTTP/1.1 200 ok\n" ++
- "Content-Length:32\r\n\n"
- "<HTML><BODY>foobar</BODY></HTML>";
- _ ->
- DefaultResponse
- end,
-
- tsp("handle_http_msg -> Msg: ~p", [Msg]),
- case Msg of
- ok ->
- %% Previously, this resulted in an {error, einval}. Now what?
- ok;
- close ->
- %% Nothing to send, just close
- Close(Socket);
- _ when is_list(Msg) orelse is_binary(Msg) ->
- Send(Socket, Msg)
- end,
- tsp("handle_http_msg -> done"),
- NextRequest.
-
-ensure_host_header_with_port([]) ->
- false;
-ensure_host_header_with_port(["host: " ++ Host| _]) ->
- case string:tokens(Host, [$:]) of
- [ActualHost, Port] ->
- tsp("ensure_host_header_with_port -> "
- "~n ActualHost: ~p"
- "~n Port: ~p", [ActualHost, Port]),
- true;
- _ ->
- false
- end;
-ensure_host_header_with_port([_|T]) ->
- ensure_host_header_with_port(T).
-
-auth_header([]) ->
- auth_header_not_found;
-auth_header(["authorization:" ++ Value | _]) ->
- {ok, string:strip(Value)};
-auth_header([_ | Tail]) ->
- auth_header(Tail).
-
-handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
- case string:tokens(base64:decode_to_string(UserInfo), ":") of
- ["alladin", "sesame"] = Auth ->
- test_server:format("Auth: ~p~n", [Auth]),
- DefaultResponse;
- Other ->
- test_server:format("UnAuth: ~p~n", [Other]),
- Challange
- end.
-
-check_cookie([]) ->
- tsf(no_cookie_header);
-check_cookie(["cookie:" ++ _Value | _]) ->
- ok;
-check_cookie([_Head | Tail]) ->
- check_cookie(Tail).
-
-content_length([]) ->
- 0;
-content_length(["content-length:" ++ Value | _]) ->
- list_to_integer(string:strip(Value));
-content_length([_Head | Tail]) ->
- content_length(Tail).
-
-%% -------------------------------------------------------------------------
-
-simple_request_and_verify(Config,
- Method, Request, HttpOpts, Opts, VerifyResult)
- when (is_list(Config) andalso
- is_atom(Method) andalso
- is_list(HttpOpts) andalso
- is_list(Opts) andalso
- is_function(VerifyResult, 1)) ->
- tsp("request_and_verify -> entry with"
- "~n Method: ~p"
- "~n Request: ~p"
- "~n HttpOpts: ~p"
- "~n Opts: ~p", [Method, Request, HttpOpts, Opts]),
- case ?config(local_server, Config) of
- ok ->
- tsp("request_and_verify -> local-server running"),
- Result = (catch httpc:request(Method, Request, HttpOpts, Opts)),
- VerifyResult(Result);
- _ ->
- tsp("request_and_verify -> local-server *not* running - skip"),
- hard_skip("Local http-server not running")
- end.
-
-
-
-
-not_implemented_yet() ->
- exit(not_implemented_yet).
-
-p(F) ->
- p(F, []).
-
-p(F, A) ->
- io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]).
-
-tsp(F) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE]).
-tsp(F, A) ->
- inets_test_lib:tsp("[~w]" ++ F, [?MODULE|A]).
-
-tsf(Reason) ->
- test_server:fail(Reason).
-
-
-dummy_ssl_server_hang(Caller, IpV, SslOpt) ->
- Pid = spawn(httpc_SUITE, dummy_ssl_server_hang_init, [Caller, IpV, SslOpt]),
- receive
- {port, Port} ->
- {Pid, Port}
- end.
-
-dummy_ssl_server_hang_init(Caller, IpV, SslOpt) ->
- {ok, ListenSocket} =
- case IpV of
- ipv4 ->
- ssl:listen(0, [binary, inet, {packet, 0},
- {reuseaddr,true},
- {active, false}] ++ SslOpt);
- ipv6 ->
- ssl:listen(0, [binary, inet6, {packet, 0},
- {reuseaddr,true},
- {active, false}] ++ SslOpt)
- end,
- {ok, {_,Port}} = ssl:sockname(ListenSocket),
- tsp("dummy_ssl_server_hang_init -> Port: ~p", [Port]),
- Caller ! {port, Port},
- {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
- dummy_ssl_server_hang_loop(AcceptSocket).
-
-dummy_ssl_server_hang_loop(_) ->
- %% Do not do ssl:ssl_accept as we
- %% want to time out the underlying gen_tcp:connect
- receive
- stop ->
- ok
- end.
-
-hard_skip(Reason) ->
- throw(skip(Reason)).
-
-skip(Reason) ->
- {skip, Reason}.