aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/doc/src/Makefile1
-rw-r--r--lib/inets/doc/src/mod_security.xml3
-rw-r--r--lib/inets/doc/src/notes.xml79
-rw-r--r--lib/inets/src/http_client/httpc_response.erl31
-rw-r--r--lib/inets/src/http_server/httpd_file.erl3
-rw-r--r--lib/inets/test/httpc_SUITE.erl98
-rw-r--r--lib/inets/test/httpd_SUITE.erl16
7 files changed, 194 insertions, 37 deletions
diff --git a/lib/inets/doc/src/Makefile b/lib/inets/doc/src/Makefile
index 29b8678cda..cbc0e384d8 100644
--- a/lib/inets/doc/src/Makefile
+++ b/lib/inets/doc/src/Makefile
@@ -115,6 +115,7 @@ pdf: $(TOP_PDF_FILE)
html: gifs $(HTML_REF_MAN_FILE)
clean clean_docs: clean_html clean_man clean_pdf
+ rm -rf $(XMLDIR)
rm -f errs core *~
man: $(MAN3_FILES)
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index ec8d6ec42c..d65d2ff998 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -135,7 +135,8 @@
<type>
<v>What = atom()</v>
<v>Port = integer()</v>
- <v>Address = {A,B,C,D} | string() &lt;v>Dir = string()</v>
+ <v>Address = {A,B,C,D} | string()</v>
+ <v>Dir = string()</v>
<v>Data = [Info]</v>
<v>Info = {Name, Value}</v>
</type>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 81f5c69276..6c4d4cb107 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -35,23 +35,23 @@
<section><title>Inets 7.0.1</title>
- <section><title>Fixed Bugs and Malfunctions</title>
- <list>
- <item>
- <p>
- Change status code for no mod found to handle request to
- 501</p>
- <p>
- Own Id: OTP-15215</p>
- </item>
- </list>
- </section>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
-</section>
+ </section>
-<section><title>Inets 7.0</title>
+ <section><title>Inets 7.0</title>
- <section><title>Fixed Bugs and Malfunctions</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
@@ -95,7 +95,6 @@
</list>
</section>
-
<section><title>Improvements and New Features</title>
<list>
<item>
@@ -107,8 +106,58 @@
</list>
</section>
+ </section>
+
+ <section><title>Inets 6.5.2.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
</section>
+<section><title>Inets 6.5.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section><title>Inets 6.5.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Options added for setting low-level properties on the
+ underlying TCP connections. The options are:
+ <c>sock_ctrl</c>, <c>sock_data_act</c> and
+ <c>sock_data_pass</c>. See the manual for details.</p>
+ <p>
+ Own Id: OTP-15120 Aux Id: ERIERL-192 </p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
<section><title>Inets 6.5.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl
index 0f3bd0a06d..78d6b4ed24 100644
--- a/lib/inets/src/http_client/httpc_response.erl
+++ b/lib/inets/src/http_client/httpc_response.erl
@@ -423,23 +423,24 @@ resolve_uri(Scheme, Host, Port, Path, Query, URI) ->
resolve_uri(Scheme, Host, Port, Path, Query, URI, #{}).
%%
resolve_uri(Scheme, Host, Port, Path, Query, URI, Map0) ->
- case maps:is_key(scheme, URI) of
- true ->
- Port = get_port(URI),
+ case maps:get(scheme, URI, undefined) of
+ undefined ->
+ Port0 = get_port(Scheme, URI),
+ Map = Map0#{scheme => Scheme,
+ port => Port0},
+ resolve_authority(Host, Port, Path, Query, URI, Map);
+ URIScheme ->
+ Port0 = get_port(URIScheme, URI),
maybe_add_query(
- Map0#{scheme => maps:get(scheme, URI),
- host => maps:get(host, URI),
- port => Port,
- path => maps:get(path, URI)},
- URI);
- false ->
- Map = Map0#{scheme => Scheme},
- resolve_authority(Host, Port, Path, Query, URI, Map)
+ Map0#{scheme => URIScheme,
+ host => maps:get(host, URI),
+ port => Port0,
+ path => maps:get(path, URI)},
+ URI)
end.
-get_port(URI) ->
- Scheme = maps:get(scheme, URI),
+get_port(Scheme, URI) ->
case maps:get(port, URI, undefined) of
undefined ->
get_default_port(Scheme);
@@ -457,15 +458,13 @@ get_default_port("https") ->
resolve_authority(Host, Port, Path, Query, RelURI, Map) ->
case maps:is_key(host, RelURI) of
true ->
- Port = get_port(RelURI),
maybe_add_query(
Map#{host => maps:get(host, RelURI),
- port => Port,
path => maps:get(path, RelURI)},
RelURI);
false ->
Map1 = Map#{host => Host,
- port => Port},
+ port => Port},
resolve_path(Path, Query, RelURI, Map1)
end.
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index 4d419172d0..fb71834e95 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -33,6 +33,9 @@ handle_error(enoent, Op, ModData, Path) ->
handle_error(enotdir, Op, ModData, Path) ->
handle_error(404, Op, ModData, Path,
": A component of the file name is not a directory");
+handle_error(eisdir, Op, ModData, Path) ->
+ handle_error(403, Op, ModData, Path,
+ ":Ilegal operation expected a file not a directory");
handle_error(emfile, Op, _ModData, Path) ->
handle_error(500, Op, none, Path, ": Too many open files");
handle_error({enfile,_}, Op, _ModData, Path) ->
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index d43e2cc179..6e048a4d56 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -59,7 +59,8 @@ all() ->
{group, http_unix_socket},
{group, https},
{group, sim_https},
- {group, misc}
+ {group, misc},
+ {group, sim_mixed} % HTTP and HTTPS sim servers
].
groups() ->
@@ -74,7 +75,8 @@ groups() ->
{http_unix_socket, [], simulated_unix_socket()},
{https, [], real_requests()},
{sim_https, [], only_simulated()},
- {misc, [], misc()}
+ {misc, [], misc()},
+ {sim_mixed, [], sim_mixed()}
].
real_requests()->
@@ -170,6 +172,12 @@ misc() ->
wait_for_whole_response
].
+sim_mixed() ->
+ [
+ redirect_http_to_https,
+ redirect_relative_different_port
+ ].
+
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -195,7 +203,8 @@ init_per_group(misc = Group, Config) ->
Config;
-init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https->
+init_per_group(Group, Config0) when Group =:= sim_https; Group =:= https;
+ Group =:= sim_mixed ->
catch crypto:stop(),
try crypto:start() of
ok ->
@@ -238,6 +247,13 @@ end_per_group(http_unix_socket,_Config) ->
end_per_group(_, _Config) ->
ok.
+do_init_per_group(Group=sim_mixed, Config0) ->
+ % The mixed group uses two server ports (http and https), so we use
+ % different config names here.
+ Config1 = init_ssl(Config0),
+ Config2 = proplists:delete(http_port, proplists:delete(https_port, Config1)),
+ {HttpPort, HttpsPort} = server_start(Group, server_config(sim_https, Config2)),
+ [{http_port, HttpPort} | [{https_port, HttpsPort} | Config2]];
do_init_per_group(Group, Config0) ->
Config1 =
case Group of
@@ -734,6 +750,48 @@ redirect_loop(Config) when is_list(Config) ->
= httpc:request(get, {URL, []}, [], []).
%%-------------------------------------------------------------------------
+redirect_http_to_https() ->
+ [{doc, "Test that a 30X redirect from one scheme to another is handled "
+ "correctly."}].
+redirect_http_to_https(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+ TargetUrl = mixed_url(https, "/dummy.html", Config),
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
+redirect_relative_different_port() ->
+ [{doc, "Test that a 30X redirect with a relative target, but different "
+ "port, is handled correctly."}].
+redirect_relative_different_port(Config) when is_list(Config) ->
+ URL301 = mixed_url(http, "/301_custom_url.html", Config),
+
+ % We need an extra server of the same protocol here, so spawn a new
+ % HTTP-protocol one
+ Port = server_start(sim_http, []),
+ {ok, Host} = inet:gethostname(),
+ % Prefix the URI with '/' instead of a scheme
+ TargetUrl = "//" ++ Host ++ ":" ++ integer_to_list(Port) ++ "/dummy.html",
+ Headers = [{"x-test-301-url", TargetUrl}],
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(get, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], []}}
+ = httpc:request(head, {URL301, Headers}, [], []),
+
+ {ok, {{_,200,_}, [_ | _], [_|_]}}
+ = httpc:request(post, {URL301, Headers, "text/plain", "foobar"},
+ [], []).
+%%-------------------------------------------------------------------------
cookie() ->
[{doc, "Test cookies."}].
cookie(Config) when is_list(Config) ->
@@ -1559,6 +1617,21 @@ url(sim_http, UserInfo, End, Config) ->
url(sim_https, UserInfo, End, Config) ->
url(https, UserInfo, End, Config).
+% Only for use in the `mixed` test group, where both http and https
+% URLs are possible.
+mixed_url(http, End, Config) ->
+ mixed_url(http_port, End, Config);
+mixed_url(https, End, Config) ->
+ mixed_url(https_port, End, Config);
+mixed_url(PortType, End, Config) ->
+ Port = proplists:get_value(PortType, Config),
+ {ok, Host} = inet:gethostname(),
+ Start = case PortType of
+ http_port -> ?URL_START;
+ https_port -> ?TLS_URL_START
+ end,
+ Start ++ Host ++ ":" ++ integer_to_list(Port) ++ End.
+
group_name(Config) ->
GroupProp = proplists:get_value(tc_group_properties, Config),
proplists:get_value(name, GroupProp).
@@ -1587,6 +1660,9 @@ server_start(http_ipv6, HttpdConfig) ->
Serv = inets:services_info(),
{value, {_, _, Info}} = lists:keysearch(Pid, 2, Serv),
proplists:get_value(port, Info);
+server_start(sim_mixed, Config) ->
+ % For the mixed http/https case, we start two servers and return both ports.
+ {server_start(sim_http, []), server_start(sim_https, Config)};
server_start(_, HttpdConfig) ->
{ok, Pid} = inets:start(httpd, HttpdConfig),
Serv = inets:services_info(),
@@ -1645,6 +1721,8 @@ start_apps(https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(sim_https) ->
inets_test_lib:start_apps([crypto, public_key, ssl]);
+start_apps(sim_mixed) ->
+ inets_test_lib:start_apps([crypto, public_key, ssl]);
start_apps(_) ->
ok.
@@ -2089,6 +2167,20 @@ handle_uri(_,"/301_rel_uri.html",_,_,_,_) ->
"Content-Length:" ++ integer_to_list(length(Body))
++ "\r\n\r\n" ++ Body;
+handle_uri("HEAD","/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:0\r\n\r\n";
+
+handle_uri(_,"/301_custom_url.html",_,Headers,_,_) ->
+ NewUri = proplists:get_value("x-test-301-url", Headers),
+ Body = "<HTML><BODY><a href=" ++ NewUri ++
+ ">New place</a></BODY></HTML>",
+ "HTTP/1.1 301 Moved Permanently\r\n" ++
+ "Location:" ++ NewUri ++ "\r\n" ++
+ "Content-Length:" ++ integer_to_list(length(Body))
+ ++ "\r\n\r\n" ++ Body;
handle_uri("HEAD","/302.html",Port,_,Socket,_) ->
NewUri = url_start(Socket) ++
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 1cb9f58416..9777c9b68e 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -457,8 +457,19 @@ get(Config) when is_list(Config) ->
{header, "Content-Type", "text/html"},
{header, "Date"},
{header, "Server"},
+ {version, Version}]),
+
+ ok = httpd_test_lib:verify_request(proplists:get_value(type, Config), Host,
+ proplists:get_value(port, Config),
+ transport_opts(Type, Config),
+ proplists:get_value(node, Config),
+ http_request("GET /open/ ", Version, Host),
+ [{statuscode, 403},
+ {header, "Content-Type", "text/html"},
+ {header, "Date"},
+ {header, "Server"},
{version, Version}]).
-
+
basic_auth_1_1(Config) when is_list(Config) ->
basic_auth([{http_version, "HTTP/1.1"} | Config]).
@@ -2035,7 +2046,8 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
- mod_trace, mod_esi, mod_cgi, mod_dir, mod_get, mod_head]}].
+ mod_trace, mod_esi, mod_cgi, mod_get, mod_head]}].
+
not_sup_conf() ->
[{modules, [mod_get]}].