summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngela Anderton Andin <ingela@erlang.org>2019-11-27 10:22:16 +0100
committerIngela Anderton Andin <ingela@erlang.org>2019-12-13 15:20:54 +0100
commit2d3c0c06dcbb781c9551badcb802ee43d6c9cef7 (patch)
tree4371d569b54154f7aa4bf65867365933a48a16ca
parentb8a78bbc1498fb7f5f090897a4fcb3845b2082ec (diff)
downloaderlang-2d3c0c06dcbb781c9551badcb802ee43d6c9cef7.tar.gz
inets: httpd - remove use of http_uri and mod_esi eval API
The removal of http_uri also further motivates removal of deprecated mod_esi eval API as it makes uses of non standard URIs
-rw-r--r--lib/inets/doc/src/http_server.xml30
-rw-r--r--lib/inets/doc/src/http_uri.xml9
-rw-r--r--lib/inets/doc/src/httpd.xml10
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl2
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl35
-rw-r--r--lib/inets/src/http_lib/http_uri.erl8
-rw-r--r--lib/inets/src/http_server/httpd.erl17
-rw-r--r--lib/inets/src/http_server/httpd_example.erl151
-rw-r--r--lib/inets/src/http_server/httpd_request.erl30
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl8
-rw-r--r--lib/inets/src/http_server/httpd_util.erl115
-rw-r--r--lib/inets/src/http_server/mod_dir.erl4
-rw-r--r--lib/inets/src/http_server/mod_esi.erl123
-rw-r--r--lib/inets/src/inets_app/inets.app.src4
-rw-r--r--lib/inets/test/http_format_SUITE.erl52
-rw-r--r--lib/inets/test/httpd_SUITE.erl63
-rw-r--r--lib/inets/test/httpd_basic_SUITE.erl4
-rw-r--r--lib/inets/test/httpd_test_lib.erl4
-rw-r--r--lib/stdlib/src/otp_internal.erl20
-rw-r--r--system/doc/general_info/deprecations.xml11
-rw-r--r--system/doc/general_info/scheduled_for_removal.xml13
21 files changed, 282 insertions, 431 deletions
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index e3eac14ab0..865abc6f5f 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -233,36 +233,6 @@ http://your.server.org/***/Module[:/]Function(?QueryString|/PathInfo)</code>
see <seealso marker="mod_esi">mod_esi(3)</seealso>.</p>
</section>
- <section>
- <title>EVAL Scheme</title>
- <p>The eval scheme is straight-forward and does not mimic the
- behavior of plain CGI. An URL that calls an Erlang <c>eval</c>
- function has the following syntax:</p>
- <code type="none">
-http://your.server.org/***/Mod:Func(Arg1,...,ArgN)</code>
- <p>*** depends on how the ErlScriptAlias config
- directive has been used.</p>
- <p>The module <c>Mod</c> referred to must be found in the code
- path and data returned by the function <c>Func</c> is passed
- back to the client. Data returned from the
- function must take the form as specified in
- the CGI specification. For implementation details of the ESI
- callback function,
- see <seealso marker="mod_esi">mod_esi(3)</seealso>.</p>
- <note>
- <p>The eval scheme can seriously threaten the
- integrity of the Erlang node housing a web server, for
- example:</p>
- <code type="none">
-http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[])))</code>
- <p>This effectively closes down the Erlang node.
- Therefore, use the erl scheme instead, until this
- security breach is fixed.</p>
- <p>Today there are no good ways of solving this problem
- and therefore the eval scheme can be removed in future
- release of <c>Inets</c>.</p>
- </note>
- </section>
</section>
</section>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 6d3547f4fe..7fc524ff7f 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -31,12 +31,13 @@
</header>
<module since="OTP R15B01">http_uri</module>
- <modulesummary>URI utility module</modulesummary>
+ <modulesummary>Old URI utility module, use uri_string instead</modulesummary>
<description>
- <p>This module provides utility functions for working with URIs,
- according to
- <url href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</url>.</p>
+ <p>This module is deprecated since OTP 23.
+ Use the module <seealso marker="stdlib:uri_string">uri_string</seealso> to properly handle URIs,
+ this is the recommend module since OTP 21.
+ </p>
</description>
<section>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 8582f1bf81..19dd0c0abf 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -624,16 +624,8 @@ Transport: TLS
<c>mod_esi:deliver/2</c>. Default is <c>15</c>. This is only relevant
for scripts that use the erl scheme.</p>
</item>
-
- <tag><marker id="prop_esi_timeout"></marker>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
- <item>
- <p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
- Same as <c>erl_script_alias</c> but for scripts
- using the eval scheme. This is only supported
- for backwards compatibility. The eval scheme is deprecated.</p>
- </item>
</taglist>
-
+
<marker id="props_log"></marker>
<p><em>Log Properties - Requires mod_log</em></p>
<taglist>
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index b1c5cf13bb..3f91ae062c 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1637,7 +1637,7 @@ host_header(#http_request_h{host = Host}, _) ->
%% Handles headers_as_is
host_header(_, URI) ->
- {ok, {_, _, Host, _, _, _}} = http_uri:parse(URI),
+ #{host := Host} = uri_string:parse(URI),
Host.
tls_upgrade(#state{status =
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 0dc0483fa9..ba561100a1 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -472,10 +472,10 @@ handle_call(which_cookies, _, #state{cookie_db = CookieDb} = State) ->
handle_call({which_cookies, Url, Options}, _,
#state{cookie_db = CookieDb} = State) ->
?hcrv("which cookies", [{url, Url}, {options, Options}]),
- case uri_parse(Url, Options) of
- {ok, {Scheme, _, Host, Port, Path, _}} ->
+ case uri_parse(Url) of
+ {ok, {Scheme, Host, Port, Path}} ->
CookieHeaders =
- httpc_cookie:header(CookieDb, Scheme, {Host, Port}, Path),
+ httpc_cookie:header(CookieDb, erlang:list_to_existing_atom(Scheme), {Host, Port}, Path),
{reply, CookieHeaders, State};
{error, _} = ERROR ->
{reply, ERROR, State}
@@ -948,14 +948,31 @@ make_db_name(ProfileName, Post) ->
%%--------------------------------------------------------------------------
%% These functions is just simple wrappers to parse specifically HTTP URIs
%%--------------------------------------------------------------------------
+uri_parse(URI) ->
+ case uri_string:parse(uri_string:normalize(URI)) of
+ #{scheme := Scheme,
+ host := Host,
+ port := Port,
+ path := Path} ->
+ {ok, {Scheme, Host, Port, Path}};
+ #{scheme := Scheme,
+ host := Host,
+ path := Path} ->
+ {ok, {Scheme, Host, scheme_default_port(Scheme), Path}};
+ Other ->
+ {error, maybe_error(Other)}
+ end.
-scheme_defaults() ->
- [{http, 80}, {https, 443}].
-
-uri_parse(URI, Opts) ->
- http_uri:parse(URI, [{scheme_defaults, scheme_defaults()} | Opts]).
-
+maybe_error({error, Atom, Term}) ->
+ {Atom, Term};
+maybe_error(Other) ->
+ {unexpected, Other}.
+scheme_default_port("http") ->
+ 80;
+scheme_default_port("https") ->
+ 443.
+
%%--------------------------------------------------------------------------
diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl
index 6805b0293d..f9a4c697c1 100644
--- a/lib/inets/src/http_lib/http_uri.erl
+++ b/lib/inets/src/http_lib/http_uri.erl
@@ -61,6 +61,14 @@
scheme_defaults/0,
encode/1, decode/1]).
+
+-deprecated({parse, 1, next_major_release}).
+-deprecated({parse, 2, next_major_release}).
+-deprecated({encode, 1, next_major_release}).
+-deprecated({decode, 1, next_major_release}).
+-deprecated({scheme_defaults, 0, next_major_release}).
+
+
-export_type([uri/0,
user_info/0,
scheme/0, default_scheme_port_number/0,
diff --git a/lib/inets/src/http_server/httpd.erl b/lib/inets/src/http_server/httpd.erl
index 66e2c2400d..08f2dfdc16 100644
--- a/lib/inets/src/http_server/httpd.erl
+++ b/lib/inets/src/http_server/httpd.erl
@@ -44,13 +44,14 @@
info/3
]).
+-deprecated({parse_query, 1, next_major_release}).
+
%%%========================================================================
%%% API
%%%========================================================================
parse_query(String) ->
- SplitString = re:split(String,"[&;]", [{return, list}]),
- foreach(SplitString).
+ uri_string:dissect_query(String).
reload_config(Config = [Value| _], Mode) when is_tuple(Value) ->
do_reload_config(Config, Mode);
@@ -252,18 +253,6 @@ unblock(Addr, Port, Profile) when is_integer(Port) ->
{error,not_started}
end.
-foreach([]) ->
- [];
-foreach([KeyValue|Rest]) ->
- Plus2Space = re:replace(KeyValue,"[\+]"," ", [{return,list}, global]),
- case re:split(Plus2Space,"=", [{return, list}]) of
- [Key|Value] ->
- [{http_uri:decode(Key),
- http_uri:decode(lists:flatten(Value))}|foreach(Rest)];
- _ ->
- foreach(Rest)
- end.
-
make_name(Addr, Port, Profile) ->
httpd_util:make_name("httpd", Addr, Port, Profile).
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index 3c25ca336f..78b781aa96 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -19,13 +19,27 @@
%%
%%
-module(httpd_example).
--export([print/1]).
--export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2,new_status_and_location/2]).
--export([newformat/3, post_chunked/3, post_204/3, ignore_invalid_header/3]).
-%% These are used by the inets test-suite
--export([delay/1, chunk_timeout/3, get_chunks/3]).
+-export([print/3,
+ get/3,
+ put/3,
+ post/3,
+ yahoo/3,
+ test1/3,
+ get_bin/3,
+ peer/3,
+ new_status_and_location/3,
+ newformat/3,
+ post_chunked/3,
+ post_204/3,
+ ignore_invalid_header/3,
+ delay/3,
+ chunk_timeout/3,
+ get_chunks/3]).
+%% ------------------------------------------------------
+print(SessionID, _Env, Input) ->
+ mod_esi:deliver(SessionID, print(Input)).
print(String) ->
[header(),
@@ -33,7 +47,11 @@ print(String) ->
String++"\n",
footer()].
-test1(Env, []) ->
+%% ------------------------------------------------------
+test1(SessionID, Env, _Input) ->
+ mod_esi:deliver(SessionID, test1(Env)).
+
+test1(Env) ->
io:format("Env:~p~n",[Env]),
["<html>",
"<head>",
@@ -44,9 +62,10 @@ test1(Env, []) ->
"<h2>Stuff</h2>",
"</body>",
"</html>"].
-
-
-get(_Env,[]) ->
+%% ------------------------------------------------------
+get(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, do_get(Env, Input)).
+do_get(_Env,[]) ->
[header(),
top("GET Example"),
"<FORM ACTION=\"/cgi-bin/erl/httpd_example:get\" METHOD=GET>
@@ -55,24 +74,35 @@ get(_Env,[]) ->
<INPUT TYPE=\"submit\"><BR>
</FORM>" ++ "\n",
footer()];
-
-get(Env,Input) ->
+do_get(Env,Input) ->
default(Env,Input).
+%% ------------------------------------------------------
+put(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, do_put(Env, Input)).
-put(Env,{Input,_Body}) ->
+do_put(Env,{Input,_Body}) ->
default(Env,Input);
-put(Env,Input) ->
+do_put(Env,Input) ->
default(Env,Input).
+%% ------------------------------------------------------
+get_bin(SessionID, Env, Input) ->
+ Header = header(),
+ IoData = get_bin(Env, Input),
+ Size = erlang:iolist_size(IoData),
+ mod_esi:deliver(SessionID, ["Content-Length:" ++ erlang:integer_to_list(Size) ++ "\r\n",
+ Header, IoData]).
get_bin(_Env,_Input) ->
- [list_to_binary(header()),
- list_to_binary(top("GET Example")),
+ [list_to_binary(top("GET Example")),
list_to_binary("<FORM ACTION=\"/cgi-bin/erl/httpd_example:get\" METHOD=GET>
<B>Input:</B> <INPUT TYPE=\"text\" NAME=\"input1\">
<INPUT TYPE=\"text\" NAME=\"input2\">
<INPUT TYPE=\"submit\"><BR>
</FORM>" ++ "\n"),
list_to_binary(footer())].
+%% ------------------------------------------------------
+post(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, post(Env, Input)).
post(_Env,[]) ->
[header(),
@@ -86,21 +116,22 @@ post(_Env,[]) ->
post(Env,Input) ->
default(Env,Input).
+%% ------------------------------------------------------
+yahoo(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, yahoo(Env, Input)).
yahoo(_Env,_Input) ->
"Location: http://www.yahoo.com\r\n\r\n".
+%% ------------------------------------------------------
+new_status_and_location(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, new_status_and_location(Env, Input)).
new_status_and_location(_Env,_Input) ->
"status:201 Created\r\n Location: http://www.yahoo.com\r\n\r\n".
+%% ------------------------------------------------------
-default(Env,Input) ->
- [header(),
- top("Default Example"),
- "<B>Environment:</B> ",io_lib:format("~p",[Env]),"<BR>\n",
- "<B>Input:</B> ",Input,"<BR>\n",
- "<B>Parsed Input:</B> ",
- io_lib:format("~p",[httpd:parse_query(Input)]),"\n",
- footer()].
+peer(SessionID, Env, Input) ->
+ mod_esi:deliver(SessionID, peer(Env, Input)).
peer(Env, _Input) ->
Header =
@@ -116,23 +147,7 @@ peer(Env, _Input) ->
io_lib:format("~p",[proplists:get_value(peer_cert, Env)]),"\n",
footer()].
-header() ->
- header("text/html").
-header(MimeType) ->
- "Content-type: " ++ MimeType ++ "\r\n\r\n".
-header(MimeType, Other) ->
- "Content-type: " ++ MimeType ++ "\r\n" ++ Other ++ "\r\n\r\n".
-
-top(Title) ->
- "<HTML>
-<HEAD>
-<TITLE>" ++ Title ++ "</TITLE>
-</HEAD>
-<BODY>\n".
-
-footer() ->
- "</BODY>
-</HTML>\n".
+%% ------------------------------------------------------
post_chunked(_SessionID, _Env, {first, _Body} = _Bodychunk) ->
{continue, {state, 1}};
@@ -150,11 +165,13 @@ post_chunked(SessionID, _Env, {last, _Body, undefined} = _Bodychunk) ->
mod_esi:deliver(SessionID, footer());
post_chunked(_, _, _Body) ->
exit(body_not_chunked).
+%% ------------------------------------------------------
post_204(SessionID, _Env, _Input) ->
mod_esi:deliver(SessionID,
["Status: 204 No Content" ++ "\r\n\r\n"]),
mod_esi:deliver(SessionID, []).
+%% ------------------------------------------------------
ignore_invalid_header(SessionID, Env, _Input) ->
case proplists:get_value(content_length, Env, undefined) of
@@ -165,7 +182,8 @@ ignore_invalid_header(SessionID, Env, _Input) ->
mod_esi:deliver(SessionID,
["Status: 500 Internal Server Error" ++ "\r\n\r\n"])
end.
-
+%% ------------------------------------------------------
+
newformat(SessionID,_,_) ->
mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("new esi format test")),
@@ -176,28 +194,16 @@ newformat(SessionID,_,_) ->
%% ------------------------------------------------------
-delay(Time) when is_integer(Time) ->
- i("httpd_example:delay(~p) -> do the delay",[Time]),
- sleep(Time),
- i("httpd_example:delay(~p) -> done, now reply",[Time]),
- delay_reply("delay ok");
-delay(Time) when is_list(Time) ->
- delay(list_to_integer(Time));
-delay({error,_Reason}) ->
- i("delay -> called with invalid time"),
- delay_reply("delay failed: invalid delay time").
+delay(SessionID,_, _) ->
+ sleep(10000),
+ Reply = delay_reply("delay ok"),
+ mod_esi:deliver(SessionID, Reply).
delay_reply(Reply) ->
[header(),
top("delay"),
Reply,
footer()].
-
-i(F) -> i(F,[]).
-i(F,A) -> io:format(F ++ "~n",A).
-
-sleep(T) -> receive after T -> ok end.
-
%% ------------------------------------------------------
chunk_timeout(SessionID, _, _StrInt) ->
@@ -224,3 +230,34 @@ get_chunks(Sid, _Env, In) ->
mod_esi:deliver(Sid, io_lib:format("Chunk ~p ms\r\n", [ChunkDelay])),
timer:sleep(ChunkDelay + BadChunkDelay),
mod_esi:deliver(Sid, "BAD Chunk\r\n").
+
+%% ------------------------------------------------------
+default(Env,Input) ->
+ [header(),
+ top("Default Example"),
+ "<B>Environment:</B> ",io_lib:format("~p",[Env]),"<BR>\n",
+ "<B>Input:</B> ",Input,"<BR>\n",
+ "<B>Parsed Input:</B> ",
+ io_lib:format("~p",[uri_string:dissect_query(Input)]),"\n",
+ footer()].
+
+header() ->
+ header("text/html").
+header(MimeType) ->
+ "Content-type: " ++ MimeType ++ "\r\n\r\n".
+header(MimeType, Other) ->
+ "Content-type: " ++ MimeType ++ "\r\n" ++ Other ++ "\r\n\r\n".
+
+top(Title) ->
+ "<HTML>
+<HEAD>
+<TITLE>" ++ Title ++ "</TITLE>
+</HEAD>
+<BODY>\n".
+
+footer() ->
+ "</BODY>
+</HTML>\n".
+
+sleep(T) -> receive after T -> ok end.
+
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 3df55c0f7a..958b122255 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -340,31 +340,13 @@ whole_body(Body, Length) ->
%% Prevent people from trying to access directories/files
%% relative to the ServerRoot.
validate_uri(RequestURI) ->
- UriNoQueryNoHex =
- case string:str(RequestURI, "?") of
- 0 ->
- (catch http_uri:decode(RequestURI));
- Ndx ->
- (catch http_uri:decode(string:left(RequestURI, Ndx)))
- end,
- case UriNoQueryNoHex of
- {'EXIT', _Reason} ->
- {error, {bad_request, {malformed_syntax, RequestURI}}};
- _ ->
- Path = format_request_uri(UriNoQueryNoHex),
- Path2 = [X||X<-string:tokens(Path, "/"),X=/="."], %% OTP-5938
- validate_path(Path2, 0, RequestURI)
+ case uri_string:normalize(RequestURI) of
+ {error, _, _} ->
+ {error, {bad_request, {malformed_syntax, RequestURI}}};
+ URI ->
+ {ok, URI}
end.
-
-validate_path([], _, _) ->
- ok;
-validate_path([".." | _], 0, RequestURI) ->
- {error, {bad_request, {forbidden, RequestURI}}};
-validate_path([".." | Rest], N, RequestURI) ->
- validate_path(Rest, N - 1, RequestURI);
-validate_path([_ | Rest], N, RequestURI) ->
- validate_path(Rest, N + 1, RequestURI).
-
+
validate_version("HTTP/1.1") ->
true;
validate_version("HTTP/1.0") ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index e48555f4d7..e82b1c46e9 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -400,9 +400,9 @@ handle_http_msg({_, _, Version, {_, _}, _},
handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
#state{status = accept, mod = ModData} = State) ->
case httpd_request:validate(Method, Uri, Version) of
- ok ->
+ {ok, NormalizedURI} ->
{ok, NewModData} =
- httpd_request:update_mod_data(ModData, Method, Uri,
+ httpd_request:update_mod_data(ModData, Method, NormalizedURI,
Version, Headers),
case is_host_specified_if_required(NewModData#mod.absolute_uri,
@@ -421,10 +421,6 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
httpd_response:send_status(ModData#mod{http_version = Version},
501, {Method, Uri, Version}, {not_sup, What}),
{stop, normal, State#state{response_sent = true}};
- {error, {bad_request, {forbidden, URI}}} ->
- httpd_response:send_status(ModData#mod{http_version = Version},
- 403, URI),
- {stop, normal, State#state{response_sent = true}};
{error, {bad_request, {malformed_syntax, URI}}} ->
httpd_response:send_status(ModData#mod{http_version = Version},
400, URI, {malformed_syntax, URI}),
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 6b3b2c9660..05cff30243 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -167,7 +167,7 @@ reason_phrase(_) -> "Internal Server Error".
%% message
message(301,URL,_) ->
- "The document has moved <A HREF=\""++ maybe_encode(URL) ++"\">here</A>.";
+ "The document has moved <A HREF=\""++ html_encode(uri_string:normalize(URL)) ++"\">here</A>.";
message(304, _URL,_) ->
"The document has not been changed.";
message(400, none, _) ->
@@ -184,11 +184,11 @@ browser doesn't understand how to supply
the credentials required.";
message(403,RequestURI,_) ->
"You don't have permission to access " ++
- html_encode(RequestURI) ++
+ html_encode(uri_string:normalize(RequestURI)) ++
" on this server.";
message(404,RequestURI,_) ->
"The requested URL " ++
- html_encode(RequestURI) ++
+ html_encode(uri_string:normalize(RequestURI)) ++
" was not found on this server.";
message(408, Timeout, _) ->
Timeout;
@@ -212,7 +212,7 @@ message(501,{Method, RequestURI, HTTPVersion}, _ConfigDB) ->
is_atom(Method) ->
atom_to_list(Method) ++
" to " ++
- html_encode(RequestURI) ++
+ html_encode(uri_string:normalize(RequestURI)) ++
" (" ++ HTTPVersion ++ ") not supported.";
is_list(Method) ->
Method ++
@@ -225,23 +225,9 @@ message(503, String, _ConfigDB) ->
"This service in unavailable due to: " ++ html_encode(String);
message(_, ReasonPhrase, _) ->
html_encode(ReasonPhrase).
-
-maybe_encode(URI) ->
- Decoded = try http_uri:decode(URI) of
- N -> N
- catch
- error:_ -> URI
- end,
- http_uri:encode(Decoded).
-
+
html_encode(String) ->
- try http_uri:decode(String) of
- Decoded when is_list(Decoded) ->
- http_util:html_encode(Decoded)
- catch
- _:_ ->
- http_util:html_encode(String)
- end.
+ http_util:html_encode(String).
%%convert_rfc_date(Date)->{{YYYY,MM,DD},{HH,MIN,SEC}}
@@ -422,21 +408,26 @@ flatlength([],L) ->
%% split_path
-split_path(Path) ->
- case re:run(Path,"[\?].*\$", [{capture, first}]) of
- %% A QUERY_STRING exists!
- {match,[{Start,Length}]} ->
- {http_uri:decode(string:substr(Path,1,Start)),
- string:substr(Path,Start+1,Length)};
- %% A possible PATH_INFO exists!
- nomatch ->
- split_path(Path,[])
+split_path(URI) ->
+ case uri_string:normalize(URI, [return_map]) of
+ #{fragment := Fragment,
+ path := Path,
+ query := Query} ->
+ {Path, add_hashmark(Query, Fragment)};
+ #{path := Path,
+ query := Query} ->
+ {Path, Query};
+ #{path := Path} ->
+ split_path(Path, [])
end.
+add_hashmark(Query, Fragment) ->
+ Query ++ "#" ++ Fragment.
+
split_path([],SoFar) ->
- {http_uri:decode(lists:reverse(SoFar)),[]};
+ {lists:reverse(SoFar),[]};
split_path([$/|Rest],SoFar) ->
- Path=http_uri:decode(lists:reverse(SoFar)),
+ Path=lists:reverse(SoFar),
case file:read_file_info(Path) of
{ok,FileInfo} when FileInfo#file_info.type =:= regular ->
{Path,[$/|Rest]};
@@ -450,56 +441,20 @@ split_path([C|Rest],SoFar) ->
%% split_script_path
-split_script_path(Path) ->
- case split_script_path(Path, []) of
- {Script, AfterPath} ->
- {PathInfo, QueryString} = pathinfo_querystring(AfterPath),
- {Script, {PathInfo, QueryString}};
- not_a_script ->
- not_a_script
- end.
-pathinfo_querystring(Str) ->
- pathinfo_querystring(Str, []).
-pathinfo_querystring([], SoFar) ->
- {lists:reverse(SoFar), []};
-pathinfo_querystring([$?|Rest], SoFar) ->
- {lists:reverse(SoFar), Rest};
-pathinfo_querystring([C|Rest], SoFar) ->
- pathinfo_querystring(Rest, [C|SoFar]).
-
-split_script_path([$?|QueryString], SoFar) ->
- Path = http_uri:decode(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok,FileInfo} when FileInfo#file_info.type =:= regular ->
- {Path, [$?|QueryString]};
- {ok, _FileInfo} ->
- not_a_script;
- {error, _Reason} ->
- not_a_script
- end;
-split_script_path([], SoFar) ->
- Path = http_uri:decode(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok,FileInfo} when FileInfo#file_info.type =:= regular ->
- {Path, []};
- {ok, _FileInfo} ->
- not_a_script;
- {error, _Reason} ->
- not_a_script
- end;
-split_script_path([$/|Rest], SoFar) ->
- Path = http_uri:decode(lists:reverse(SoFar)),
- case file:read_file_info(Path) of
- {ok, FileInfo} when FileInfo#file_info.type =:= regular ->
- {Path, [$/|Rest]};
- {ok, _FileInfo} ->
- split_script_path(Rest, [$/|SoFar]);
- {error, _Reason} ->
- split_script_path(Rest, [$/|SoFar])
- end;
-split_script_path([C|Rest], SoFar) ->
- split_script_path(Rest,[C|SoFar]).
+split_script_path(URI) ->
+ case uri_string:normalize(URI, [return_map]) of
+ #{fragment := _Fragment,
+ path := _Path,
+ query := _Query} ->
+ not_a_script;
+ #{path := Path,
+ query := Query} ->
+ {Script, PathInfo} = split_path(Path, []),
+ {Script, {PathInfo, Query}};
+ #{path := Path} ->
+ split_path(Path, [])
+ end.
%% suffix
diff --git a/lib/inets/src/http_server/mod_dir.erl b/lib/inets/src/http_server/mod_dir.erl
index 2a90575e7d..ad2ee1d994 100644
--- a/lib/inets/src/http_server/mod_dir.erl
+++ b/lib/inets/src/http_server/mod_dir.erl
@@ -57,9 +57,7 @@ do_dir(Info) ->
%% Is it a directory?
case file:read_file_info(DefaultPath) of
{ok,FileInfo} when FileInfo#file_info.type == directory ->
- DecodedRequestURI =
- http_uri:decode(Info#mod.request_uri),
- case dir(DefaultPath,string:strip(DecodedRequestURI,right,$/),
+ case dir(DefaultPath,string:strip( Info#mod.request_uri,right,$/),
Info#mod.config_db) of
{ok, Dir} ->
LastModified =
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 45dacea3e9..00268aefec 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -106,16 +106,6 @@ store({erl_script_alias, {Name, Modules}} = Conf, _)
{error, {wrong_type, {erl_script_alias, Error}}}
end;
-store({eval_script_alias, {Name, Modules}} = Conf, _)
- when is_list(Name)->
- try httpd_util:modules_validate(Modules) of
- ok ->
- {ok, Conf}
- catch
- throw:Error ->
- {error, {wrong_type, {eval_script_alias, Error}}}
- end;
-
store({erl_script_alias, Value}, _) ->
{error, {wrong_type, {erl_script_alias, Value}}};
store({erl_script_timeout, TimeoutSec}, _)
@@ -135,8 +125,6 @@ store({erl_script_nocache, Value}, _) ->
%%%========================================================================
generate_response(ModData) ->
case scheme(ModData#mod.request_uri, ModData#mod.config_db) of
- {eval, ESIBody, Modules} ->
- eval(ModData, ESIBody, Modules);
{erl, ESIBody, Modules} ->
erl(ModData, ESIBody, Modules);
no_scheme ->
@@ -146,12 +134,7 @@ generate_response(ModData) ->
scheme(RequestURI, ConfigDB) ->
case match_script(RequestURI, ConfigDB, erl_script_alias) of
no_match ->
- case match_script(RequestURI, ConfigDB, eval_script_alias) of
- no_match ->
- no_scheme;
- {EsiBody, ScriptModules} ->
- {eval, EsiBody, ScriptModules}
- end;
+ no_scheme;
{EsiBody, ScriptModules} ->
{erl, EsiBody, ScriptModules}
end.
@@ -176,10 +159,7 @@ match_esi_script(RequestURI, [{Alias,Modules} | Rest], AliasType) ->
end.
alias_match_str(Alias, erl_script_alias) ->
- "^" ++ Alias ++ "/";
-alias_match_str(Alias, eval_script_alias) ->
- "^" ++ Alias ++ "\\?".
-
+ "^" ++ Alias ++ "/".
%%------------------------ Erl mechanism --------------------------------
@@ -260,8 +240,8 @@ generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
case erl_scheme_webpage_chunk(Module, Function,
Env, Input, ModData) of
{error, erl_scheme_webpage_chunk_undefined} ->
- erl_scheme_webpage_whole(Module, Function, Env, Input,
- ModData);
+ {proceed, [{status, {404, ModData#mod.request_uri, "Not found"}}
+ | ModData#mod.data]};
ResponseResult ->
ResponseResult
end;
@@ -271,38 +251,7 @@ generate_webpage(ModData, ESIBody, Modules, Module, FunctionName,
++ ESIBody)}} | ModData#mod.data]}
end.
-%% Old API that waits for the dymnamic webpage to be totally generated
-%% before anythig is sent back to the client.
-erl_scheme_webpage_whole(Mod, Func, Env, Input, ModData) ->
- case (catch Mod:Func(Env, Input)) of
- {'EXIT',{undef, _}} ->
- {proceed, [{status, {404, ModData#mod.request_uri, "Not found"}}
- | ModData#mod.data]};
- {'EXIT',Reason} ->
- {proceed, [{status, {500, none, Reason}} |
- ModData#mod.data]};
- Response ->
- {Headers, Body} =
- httpd_esi:parse_headers(lists:flatten(Response)),
- Length = httpd_util:flatlength(Body),
- {ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
- send_headers(ModData, StatusCode,
- [{"content-length",
- integer_to_list(Length)}| NewHeaders]),
- case ModData#mod.method of
- "HEAD" ->
- {proceed, [{response, {already_sent, StatusCode, 0}} |
- ModData#mod.data]};
- _ ->
- httpd_response:send_body(ModData,
- StatusCode, Body),
- {proceed, [{response, {already_sent, StatusCode,
- Length}} |
- ModData#mod.data]}
- end
- end.
-
-%% New API that allows the dynamic wepage to be sent back to the client
+%% API that allows the dynamic wepage to be sent back to the client
%% in small chunks at the time during generation.
erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
process_flag(trap_exit, true),
@@ -314,7 +263,6 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
fun() ->
case catch Mod:Func(Self, Env, Input) of
{'EXIT', {undef,_}} ->
- %% Will force fallback on the old API
exit(erl_scheme_webpage_chunk_undefined);
{continue, _} = Continue ->
exit(Continue);
@@ -468,64 +416,3 @@ input_type([$?|_Rest]) ->
input_type([_First|Rest]) ->
input_type(Rest).
-%%------------------------ Eval mechanism --------------------------------
-
-eval(#mod{request_uri = ReqUri,
- method = "PUT",
- http_version = Version,
- data = Data}, _ESIBody, _Modules) ->
- {proceed,[{status,{501,{"PUT", ReqUri, Version},
- ?NICE("Eval mechanism doesn't support method PUT")}}|
- Data]};
-
-eval(#mod{request_uri = ReqUri,
- method = "DELETE",
- http_version = Version,
- data = Data}, _ESIBody, _Modules) ->
- {proceed,[{status,{501,{"DELETE", ReqUri, Version},
- ?NICE("Eval mechanism doesn't support method DELETE")}}|
- Data]};
-
-eval(#mod{request_uri = ReqUri,
- method = "POST",
- http_version = Version,
- data = Data}, _ESIBody, _Modules) ->
- {proceed,[{status,{501,{"POST", ReqUri, Version},
- ?NICE("Eval mechanism doesn't support method POST")}}|
- Data]};
-
-eval(#mod{method = Method} = ModData, ESIBody, Modules)
- when (Method =:= "GET") orelse (Method =:= "HEAD") ->
- case is_authorized(ESIBody, Modules) of
- true ->
- case generate_webpage(ESIBody) of
- {error, Reason} ->
- {proceed, [{status, {500, none, Reason}} |
- ModData#mod.data]};
- {ok, Response} ->
- {Headers, _} =
- httpd_esi:parse_headers(lists:flatten(Response)),
- {ok, _, StatusCode} =httpd_esi:handle_headers(Headers),
- {proceed,[{response, {StatusCode, Response}} |
- ModData#mod.data]}
- end;
- false ->
- {proceed,[{status,
- {403, ModData#mod.request_uri,
- ?NICE("Client not authorized to evaluate: "
- ++ ESIBody)}} | ModData#mod.data]}
- end.
-
-generate_webpage(ESIBody) ->
- (catch erl_eval:eval_str(string:concat(ESIBody,". "))).
-
-is_authorized(_ESIBody, [all]) ->
- true;
-is_authorized(ESIBody, Modules) ->
- case re:run(ESIBody, "^[^\:(%3A)]*", [{capture, first}]) of
- {match, [{Start, Length}]} ->
- lists:member(list_to_atom(string:substr(ESIBody, Start+1, Length)),
- Modules);
- nomatch ->
- false
- end.
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index e5310fd80e..54b60ee1f7 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -43,14 +43,14 @@
httpc_sup,
httpc_cookie,
- http_uri, %% Proably will by used by server also in the future
-
%% HTTP used by both client and server
http_chunk,
http_request,
http_response,
http_transport,
http_util,
+
+ http_uri, %% Deprecated
%% HTTP server:
httpd,
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index 3ff3ed4e97..6492325701 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -454,7 +454,7 @@ validate_request_line() ->
validate_request_line(Config) when is_list(Config) ->
%% HTTP/0.9 only has GET requests
- ok =
+ {ok, "http://www.erlang/org"} =
httpd_request:validate("GET", "http://www.erlang/org", "HTTP/0.9"),
{error, {not_supported,
{"HEAD", "http://www.erlang/org", "HTTP/0.9"}}} =
@@ -467,43 +467,37 @@ validate_request_line(Config) when is_list(Config) ->
httpd_request:validate("POST", "http://www.erlang/org", "HTTP/0.9"),
%% HTTP/1.*
- ok = httpd_request:validate("HEAD", "http://www.erlang/org",
+ {ok, "http://www.erlang/org"} = httpd_request:validate("HEAD", "http://www.erlang/org",
"HTTP/1.1"),
- ok = httpd_request:validate("GET", "http://www.erlang/org",
+ {ok, "http://www.erlang/org"} = httpd_request:validate("GET", "http://www.erlang/org",
"HTTP/1.1"),
- ok = httpd_request:validate("POST","http://www.erlang/org",
- "HTTP/1.1"),
- ok = httpd_request:validate("TRACE","http://www.erlang/org",
+ {ok, "http://www.erlang/org"} = httpd_request:validate("POST","http://www.erlang/org",
"HTTP/1.1"),
+ {ok, "http://www.erlang/org"} = httpd_request:validate("TRACE","http://www.erlang/org",
+ "HTTP/1.1"),
{error, {not_supported,
{"FOOBAR", "http://www.erlang/org", "HTTP/1.1"}}} =
httpd_request:validate("FOOBAR", "http://www.erlang/org",
"HTTP/1.1"),
+ %%% Will work after normalization
+ Uri = "http://127.0.0.1:8888/../../../../../etc/passwd",
+ {ok, "http://127.0.0.1:8888/etc/passwd"} = httpd_request:validate("GET", Uri, "HTTP/1.1"),
- %% Attempts to get outside of server_root directory by relative links
- ForbiddenUri = "http://127.0.0.1:8888/../../../../../etc/passwd",
- {error, {bad_request, {forbidden, ForbiddenUri}}} =
- httpd_request:validate("GET", ForbiddenUri, "HTTP/1.1"),
-
- ForbiddenUri2 =
+ Uri2 =
"http://127.0.0.1:8888/././././././../../../../../etc/passwd",
- {error, {bad_request, {forbidden, ForbiddenUri2}}} =
- httpd_request:validate("GET", ForbiddenUri2, "HTTP/1.1"),
-
- HexForbiddenUri = "http://127.0.0.1:8888/%2e%2e/%2e%2e/%2e%2e/"
- "home/ingela/test.html",
- {error, {bad_request, {forbidden, HexForbiddenUri}}} =
- httpd_request:validate("GET", HexForbiddenUri, "HTTP/1.1"),
-
- NewForbiddenUri =
- "http://127.0.0.1:8888/foobar/../../../home/ingela/test.html",
- {error, {bad_request, {forbidden, NewForbiddenUri}}} =
- httpd_request:validate("GET", NewForbiddenUri, "HTTP/1.1"),
-
- NewForbiddenUri1 =
- "http://127.0.0.1:8888/../home/ingela/test.html",
- {error, {bad_request, {forbidden, NewForbiddenUri1}}} =
- httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1").
+ {ok, "http://127.0.0.1:8888/etc/passwd"} = httpd_request:validate("GET", Uri2, "HTTP/1.1"),
+
+ HexUri = "http://127.0.0.1:8888/%2e%2e/%2e%2e/%2e%2e/"
+ "home/foobar/test.html",
+ {ok, "http://127.0.0.1:8888/home/foobar/test.html"} = httpd_request:validate("GET", HexUri, "HTTP/1.1"),
+
+ NewUri =
+ "http://127.0.0.1:8888/foobar/../../../home/foobar/test.html",
+ {ok,"http://127.0.0.1:8888/home/foobar/test.html"} = httpd_request:validate("GET", NewUri, "HTTP/1.1"),
+
+ Uri1 =
+ "http://127.0.0.1:8888/../home/foobar/test.html",
+ {ok,"http://127.0.0.1:8888/home/foobar/test.html"} = httpd_request:validate("GET", Uri1, "HTTP/1.1").
%%-------------------------------------------------------------------------
check_content_length_encoding() ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 5af92b4a3b..52dcba94b9 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -111,16 +111,16 @@ groups() ->
{https_not_sup, [], [{group, not_sup}]},
{https_alert, [], [tls_alert]},
{http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]},
- {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]},
+ {limit, [], [content_length, max_clients_1_1]},
{custom, [], [customize, add_default]},
{reload, [], [non_disturbing_reconfiger_dies,
disturbing_reconfiger_dies,
non_disturbing_1_1,
non_disturbing_1_0,
non_disturbing_0_9,
- disturbing_1_1,
- disturbing_1_0,
- disturbing_0_9,
+ disturbing_1_1,
+ disturbing_1_0,
+ disturbing_0_9,
reload_config_file
]},
{post, [], [chunked_post, chunked_chunked_encoded_post, post_204]},
@@ -157,7 +157,6 @@ http_get() ->
get,
%%actions, Add configuration so that this test mod_action
esi,
- content_length,
bad_hex,
missing_CR,
max_header,
@@ -225,7 +224,7 @@ init_per_group(Group, Config0) when Group == https_basic;
catch crypto:stop(),
try crypto:start() of
ok ->
- init_ssl(Group, Config0)
+ init_ssl(Group, [{http_version, "HTTP/1.0"} | Config0])
catch
_:_ ->
{skip, "Crypto did not start"}
@@ -244,7 +243,7 @@ init_per_group(Group, Config0) when Group == http_basic;
Group == http_mime_types
->
ok = start_apps(Group),
- init_httpd(Group, [{type, ip_comm} | Config0]);
+ init_httpd(Group, [{http_version, "HTTP/1.0"}, {type, ip_comm} | Config0]);
init_per_group(http_1_1, Config) ->
[{http_version, "HTTP/1.1"} | Config];
init_per_group(http_1_0, Config) ->
@@ -811,19 +810,6 @@ max_clients_1_1() ->
max_clients_1_1(Config) when is_list(Config) ->
do_max_clients([{http_version, "HTTP/1.1"} | Config]).
-max_clients_1_0() ->
- [{doc, "Test max clients limit"}].
-
-max_clients_1_0(Config) when is_list(Config) ->
- do_max_clients([{http_version, "HTTP/1.0"} | Config]).
-
-max_clients_0_9() ->
- [{doc, "Test max clients limit"}].
-
-max_clients_0_9(Config) when is_list(Config) ->
- do_max_clients([{http_version, "HTTP/0.9"} | Config]).
-
-
%%-------------------------------------------------------------------------
put_not_sup() ->
[{doc, "Test unhandled request"}].
@@ -854,12 +840,6 @@ esi() ->
[{doc, "Test mod_esi"}].
esi(Config) when is_list(Config) ->
- ok = http_status("GET /eval?httpd_example:print(\"Hi!\") ",
- Config, [{statuscode, 200}]),
- ok = http_status("GET /eval?not_allowed:print(\"Hi!\") ",
- Config, [{statuscode, 403}]),
- ok = http_status("GET /eval?httpd_example:undef(\"Hi!\") ",
- Config, [{statuscode, 500}]),
ok = http_status("GET /cgi-bin/erl/httpd_example ",
Config, [{statuscode, 400}]),
ok = http_status("GET /cgi-bin/erl/httpd_example:get ",
@@ -1441,20 +1421,20 @@ do_reconfiger_dies(Config, DisturbingType) ->
Type = proplists:get_value(type, Config),
HttpdConfig = httpd:info(Server),
- BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
+ BlockRequest = http_request("GET /cgi-bin/erl/httpd_example:delay ", Version, Host),
{ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)),
inets_test_lib:send(Type, Socket, BlockRequest),
ct:sleep(100), %% Avoid possible timing issues
Pid = spawn(fun() -> httpd:reload_config([{server_name, "httpd_kill_" ++ Version},
- {port, Port}|
- proplists:delete(server_name, HttpdConfig)], DisturbingType)
- end),
+ {port, Port}|
+ proplists:delete(server_name, HttpdConfig)], DisturbingType)
+ end),
monitor(process, Pid),
exit(Pid, kill),
receive
- {'DOWN', _, _, _, _} ->
- ok
+ {'DOWN', _, _, _, _} ->
+ ok
end,
inets_test_lib:close(Type, Socket),
[{server_name, "httpd_test"}] = httpd:info(Server, [server_name]).
@@ -1475,7 +1455,8 @@ disturbing(Config) when is_list(Config)->
Port = proplists:get_value(port, Config),
Type = proplists:get_value(type, Config),
HttpdConfig = httpd:info(Server),
- BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
+
+ BlockRequest = http_request("GET /cgi-bin/erl/httpd_example:delay ", Version, Host),
{ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)),
inets_test_lib:send(Type, Socket, BlockRequest),
ct:sleep(100), %% Avoid possible timing issues
@@ -1508,7 +1489,7 @@ non_disturbing(Config) when is_list(Config)->
Type = proplists:get_value(type, Config),
HttpdConfig = httpd:info(Server),
- BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
+ BlockRequest = http_request("GET /cgi-bin/erl/httpd_example:delay ", Version, Host),
{ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)),
inets_test_lib:send(Type, Socket, BlockRequest),
ct:sleep(100), %% Avoid possible timing issues
@@ -1798,10 +1779,9 @@ do_max_clients(Config) ->
Type = proplists:get_value(type, Config),
Request = http_request("GET /index.html ", Version, Host),
- BlockRequest = http_request("GET /eval?httpd_example:delay(2000) ", Version, Host),
+ BlockRequest = http_request("GET /cgi_bin/erl/httpd_example:delay ", Version, Host),
{ok, Socket} = inets_test_lib:connect_bin(Type, Host, Port, transport_opts(Type, Config)),
inets_test_lib:send(Type, Socket, BlockRequest),
- ct:sleep(100), %% Avoid possible timing issues
ok = httpd_test_lib:verify_request(Type, Host,
Port,
transport_opts(Type, Config),
@@ -1948,6 +1928,7 @@ server_config(https_reload, Config) ->
[{keep_alive_timeout, 2}] ++ server_config(https, Config);
server_config(http_limit, Config) ->
Conf = [{max_clients, 1},
+ {disable_chunked_transfer_encoding_send, true},
%% Make sure option checking code is run
{max_content_length, 100000002}] ++ server_config(http, Config),
ct:pal("Received message ~p~n", [Conf]),
@@ -1957,7 +1938,9 @@ server_config(http_custom, Config) ->
server_config(https_custom, Config) ->
[{customize, ?MODULE}] ++ server_config(https, Config);
server_config(https_limit, Config) ->
- [{max_clients, 1}] ++ server_config(https, Config);
+ [{max_clients, 1},
+ {disable_chunked_transfer_encoding_send, true}
+ ] ++ server_config(https, Config);
server_config(http_basic_auth, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
auth_conf(ServerRoot) ++ server_config(http, Config);
@@ -2015,8 +1998,7 @@ server_config(http, Config) ->
{alias, {"/pics/", filename:join(ServerRoot,"icons") ++ "/"}},
{script_alias, {"/cgi-bin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}},
{script_alias, {"/htbin/", filename:join(ServerRoot, "cgi-bin") ++ "/"}},
- {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}},
- {eval_script_alias, {"/eval", [httpd_example, io]}}
+ {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}}
];
server_config(http_rel_path_script_alias, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
@@ -2036,8 +2018,7 @@ server_config(http_rel_path_script_alias, Config) ->
{alias, {"/pics/", filename:join(ServerRoot,"icons") ++ "/"}},
{script_alias, {"/cgi-bin/", "./cgi-bin/"}},
{script_alias, {"/htbin/", "./cgi-bin/"}},
- {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}},
- {eval_script_alias, {"/eval", [httpd_example, io]}}
+ {erl_script_alias, {"/cgi-bin/erl", [httpd_example, io]}}
];
server_config(https, Config) ->
SSLConf = proplists:get_value(ssl_conf, Config),
diff --git a/lib/inets/test/httpd_basic_SUITE.erl b/lib/inets/test/httpd_basic_SUITE.erl
index 94d22ea76c..1d3be6de57 100644
--- a/lib/inets/test/httpd_basic_SUITE.erl
+++ b/lib/inets/test/httpd_basic_SUITE.erl
@@ -302,11 +302,13 @@ escaped_url_in_error_body(Config) when is_list(Config) ->
%% Ask for a non-existing page(1)
Path = "/<b>this_is_bold<b>",
- HTMLEncodedPath = http_util:html_encode(Path),
URL2 = uri_string:recompose(#{scheme => "http",
host => "localhost",
port => Port,
path => Path}),
+
+ #{path := EncodedPath} = uri_string:parse(URL2),
+ HTMLEncodedPath = http_util:html_encode(EncodedPath),
{ok, {404, Body3}} = httpc:request(get, {URL2, []},
[{url_encode, true},
{version, "HTTP/1.0"}],
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index b6525037b2..c5efe98555 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -388,8 +388,8 @@ is_expect(RequestStr) ->
end.
%% OTP-5775, content-length
-check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.0\r\n\r\n", 200, "text/html", Length, _Body) when (Length =/= 274) ->
- ct:fail(content_length_error);
+check_body("GET /cgi-bin/erl/httpd_example:get_bin HTTP/1.1\r\n\r\n", 200, "text/html", Length, _Body) when (Length =/= 274) ->
+ ct:fail({content_length_error, Length});
check_body("GET /cgi-bin/cgi_echo HTTP/1.0\r\n\r\n", 200, "text/plain",
_, Body) ->
case size(Body) of
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index ac15825b2b..57439a5c0b 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -66,6 +66,26 @@ obsolete_1(erlang, now, 0) ->
obsolete_1(calendar, local_time_to_universal_time, 1) ->
{deprecated, {calendar, local_time_to_universal_time_dst, 1}};
+%% *** inets added in OTP 23 ***
+
+obsolete_1(http_uri, parse, 1) ->
+ {deprecated, "deprecated; use uri_string functions instead"};
+
+obsolete_1(http_uri, parse, 2) ->
+ {deprecated, "deprecated; use uri_string functions instead"};
+
+obsolete_1(http_uri, encode, 1) ->
+ {deprecated, "deprecated; use uri_string functions instead"};
+
+obsolete_1(http_uri, decode, 1) ->
+ {deprecated, "deprecated; use uri_string functions instead"};
+
+obsolete_1(http_uri, scheme_defaults, 0) ->
+ {deprecated, "deprecated; use uri_string functions instead"};
+
+obsolete_1(httpd, parse_query, 1) ->
+ {deprecated, {uri_string, dissect_query, 1}};
+
%% *** STDLIB added in OTP 22 ***
obsolete_1(sys, get_debug, 3) ->
diff --git a/system/doc/general_info/deprecations.xml b/system/doc/general_info/deprecations.xml
index 33b1935a58..69d063faf4 100644
--- a/system/doc/general_info/deprecations.xml
+++ b/system/doc/general_info/deprecations.xml
@@ -51,8 +51,17 @@
<p>For replacement functions see the
<seealso marker="crypto:new_api#the-new-api">New API</seealso>.</p>
</section>
+
+ <section>
+ <title>http_uri</title>
+ <p>Since OTP 21 the recommended module to handle URIs is
+ <seealso marker="stdlib:uri_string">uri_string</seealso>. The module
+ http_uri does not provide a implementation that satisfies the
+ RFC.
+ </p>
+ </section>
</section>
-
+
<section>
<marker id="OTP-22"/>
<title>OTP 22</title>
diff --git a/system/doc/general_info/scheduled_for_removal.xml b/system/doc/general_info/scheduled_for_removal.xml
index 078c32b051..6f3d408f82 100644
--- a/system/doc/general_info/scheduled_for_removal.xml
+++ b/system/doc/general_info/scheduled_for_removal.xml
@@ -37,6 +37,19 @@
<seealso marker="../system_principles/misc#removal">Support, Compatibility,
Deprecations, and Removal</seealso>.</p>
</section>
+
+ <section>
+ <marker id="OTP-25"/>
+ <title>OTP 25</title>
+ <section>
+ <title>http_uri</title>
+ <p>Since OTP 21 the recommended module to handle URIs is
+ <seealso marker="stdlib:uri_string">uri_string</seealso>. The module
+ http_uri does not provide a implementation that satisfies the
+ RFC. Formally deprecated since OTP-23 </p>
+ </section>
+ </section>
+
<section>
<marker id="OTP-24"/>
<title>OTP 24</title>