summaryrefslogtreecommitdiff
path: root/lib/inets
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2019-10-16 09:01:04 +0200
committerErlang/OTP <otp@erlang.org>2019-10-16 09:01:04 +0200
commit0010f52aef611fa6c2604504ebb278f4f7676710 (patch)
treebc0261cf64e53c2f2bd765033f3a69ed333f0910 /lib/inets
parentd233c924fe2de37c60b8d35898e57a8dcf6924d8 (diff)
parent6b5f1ff4c6afab8b4dac36ea129e84ab9524c084 (diff)
downloaderlang-0010f52aef611fa6c2604504ebb278f4f7676710.tar.gz
Merge branch 'ingela/main-21/inets/httpd/error-log-with-logger/OTP-16019' into maint-21
* ingela/main-21/inets/httpd/error-log-with-logger/OTP-16019: inets, httpd: Add logger error logging # Conflicts: # lib/inets/test/httpd_SUITE.erl
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/doc/src/httpd.xml76
-rw-r--r--lib/inets/include/httpd.hrl4
-rw-r--r--lib/inets/src/http_lib/http_transport.erl2
-rw-r--r--lib/inets/src/http_server/Makefile1
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl65
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl67
-rw-r--r--lib/inets/src/http_server/httpd_internal.hrl34
-rw-r--r--lib/inets/src/http_server/httpd_logger.erl143
-rw-r--r--lib/inets/src/http_server/httpd_request.erl12
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl139
-rw-r--r--lib/inets/src/http_server/httpd_response.erl39
-rw-r--r--lib/inets/src/http_server/httpd_util.erl30
-rw-r--r--lib/inets/src/http_server/mod_alias.erl7
-rw-r--r--lib/inets/src/http_server/mod_dir.erl15
-rw-r--r--lib/inets/src/http_server/mod_esi.erl6
-rw-r--r--lib/inets/src/http_server/mod_get.erl9
-rw-r--r--lib/inets/src/http_server/mod_range.erl19
-rw-r--r--lib/inets/src/http_server/mod_responsecontrol.erl18
-rw-r--r--lib/inets/src/inets_app/inets.app.src1
-rw-r--r--lib/inets/test/httpd_SUITE.erl33
20 files changed, 407 insertions, 313 deletions
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 66369e8df9..ff01a4c10c 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -353,6 +353,82 @@ text/plain asc txt</pre>
<p>By default, the value is as before, that is, <c>minimal</c>.</p>
</item>
+
+ <tag><marker id="prop_logger"></marker>{logger, Options::list()}</tag>
+ <item>
+
+ <p>Currently only one option is supported: </p>
+
+ <taglist>
+ <tag><c>{error, ServerID::atom()}</c></tag>
+ <item> <p>Produces
+ <seealso marker="kernel:logger#type-log_event">logger events</seealso>
+ on logger <seealso marker="kernel:logger#type-level">level error</seealso>
+ under the hierarchical logger <seealso marker="kernel:logger#type-log_event">domain:</seealso> <c>[otp, inets, httpd, ServerID, error]</c>
+ The built in logger formatting
+ function produces log entries from the
+ error reports:</p>
+
+ <code>
+#{server_name => string()
+ protocol => internal | 'TCP' | 'TLS' | 'HTTP',
+ transport => "TCP "| "TLS", %% Present when protocol = 'HTTP'
+ uri => string(), %% Present when protocol = 'HTTP' and URI is valid
+ peer => inet:peername(),
+ host => inet:hostname(),
+ reason => term()
+}
+</code>
+
+<p>An example of a log entry with only default settings of logger</p>
+
+<code>
+=ERROR REPORT==== 9-Oct-2019::09:33:27.350235 ===
+ Server: My Server
+ Protocol: HTTP
+Transport: TLS
+ URI: /not_there
+ Host: 127.0.1.1:80
+ Peer: 127.0.0.1:45253
+ Reason: [{statuscode,404},{description,"Object Not Found"}]
+</code>
+
+<p>Using this option makes mod_log and mod_disk_log error logs redundant.</p>
+
+ <p>Add the filter</p>
+ <code>
+{fun logger_filters:domain/2,
+ {log,equal,[otp,inets, httpd, ServerID, error]}</code>
+
+ to appropriate logger handler to handle the events. For
+ example to write the error log from an httpd server with a
+ <c>ServerID</c> of <c>my_server</c> to a file you can use the following
+ sys.config:
+
+ <code>[{kernel,
+ [{logger,
+ [{handler, http_error_test, logger_std_h,
+ #{config => #{ file => "log/http_error.log" },
+ filters => [{inets_httpd, {fun logger_filters:domain/2,
+ {log, equal,
+ [otp, inets, httpd, my_server, error]
+ }}}],
+ filter_default => stop }}]}]}].
+ </code>
+
+ <p>or if you want to add it to the default logger via an API:</p>
+
+ <code>logger:add_handler_filter(default,
+ inets_httpd,
+ {fun logger_filters:domain/2,
+ {log, equal,
+ [otp, inets, httpd, my_server, error]}}).</code>
+
+ </item>
+ </taglist>
+
+ </item>
+
<tag><marker id="prop_log_format"></marker>{log_format, common | combined}</tag>
<item>
<p>Defines if access logs are to be written according to the <c>common</c>
diff --git a/lib/inets/include/httpd.hrl b/lib/inets/include/httpd.hrl
index fb338d5c68..a4b6b40b90 100644
--- a/lib/inets/include/httpd.hrl
+++ b/lib/inets/include/httpd.hrl
@@ -24,7 +24,9 @@
-include_lib("kernel/include/file.hrl").
--record(init_data,{peername,resolve}).
+-record(init_data,{peername,
+ sockname,
+ resolve}).
-record(mod,{init_data,
data=[],
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 2e3e099e5b..d5e1d71336 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -487,4 +487,4 @@ negotiate({essl, _}, Socket, Timeout) ->
negotiate_ssl(Socket, Timeout).
negotiate_ssl(Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout).
+ ssl:handshake(Socket, Timeout).
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index 1c05d454a5..9848fd4b35 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -57,6 +57,7 @@ MODULES = \
httpd_file\
httpd_instance_sup \
httpd_log \
+ httpd_logger \
httpd_manager \
httpd_misc_sup \
httpd_request \
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index 447faec12f..d08c578acb 100644
--- a/lib/inets/src/http_server/httpd_acceptor.erl
+++ b/lib/inets/src/http_server/httpd_acceptor.erl
@@ -21,8 +21,7 @@
-module(httpd_acceptor).
-include("httpd.hrl").
--include("httpd_internal.hrl").
-%%-include("inets_internal.hrl").
+-include_lib("kernel/include/logger.hrl").
%% Internal application API
-export([start_link/7, start_link/8]).
@@ -37,34 +36,16 @@
%% start_link
start_link(Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) ->
- %% ?hdrd("start link",
- %% [{manager, Manager},
- %% {socket_type, SocketType},
- %% {address, Addr},
- %% {port, Port},
- %% {timeout, AcceptTimeout}]),
Args = [self(), Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
start_link(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
- %% ?hdrd("start link",
- %% [{manager, Manager},
- %% {socket_type, SocketType},
- %% {listen_socket, ListenSocket},
- %% {timeout, AcceptTimeout}]),
Args = [self(), Manager, SocketType, Addr, Port, ListenSocket, IpFamily,
ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
acceptor_init(Parent, Manager, SocketType, Addr, Port, {ListenOwner, ListenSocket}, IpFamily,
ConfigDb, AcceptTimeout) ->
- %% ?hdrd("acceptor init",
- %% [{parent, Parent},
- %% {manager, Manager},
- %% {socket_type, SocketType},
- %% {listen_owner, ListenOwner},
- %% {listen_socket, ListenSocket},
- %% {timeout, AcceptTimeout}]),
link(ListenOwner),
proc_lib:init_ack(Parent, {ok, self()}),
acceptor_loop(Manager, SocketType, Addr, Port,
@@ -131,21 +112,16 @@ acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket, IpFamily, ConfigDb,
%% {timeout, AcceptTimeout}]),
case (catch http_transport:accept(SocketType, ListenSocket, 50000)) of
{ok, Socket} ->
- %% ?hdrv("accepted", [{socket, Socket}]),
handle_connection(Addr, Port, Manager, ConfigDb, AcceptTimeout,
SocketType, Socket),
?MODULE:acceptor_loop(Manager, SocketType, Addr, Port,
ListenSocket, IpFamily, ConfigDb,AcceptTimeout);
{error, Reason} ->
- %% ?hdri("accept failed", [{reason, Reason}]),
- handle_error(Reason, ConfigDb),
+ handle_error(Reason, ConfigDb, ?LOCATION),
?MODULE:acceptor_loop(Manager, SocketType, Addr, Port, ListenSocket,
IpFamily, ConfigDb, AcceptTimeout);
{'EXIT', Reason} ->
- %% ?hdri("accept exited", [{reason, Reason}]),
- ReasonString =
- lists:flatten(io_lib:format("Accept exit: ~p", [Reason])),
- accept_failed(ConfigDb, ReasonString)
+ accept_failed(ConfigDb, [{accept_failed, Reason}], ?LOCATION)
end.
@@ -155,18 +131,18 @@ handle_connection(Address, Port, Manager, ConfigDb, AcceptTimeout, SocketType,
http_transport:controlling_process(SocketType, Socket, Pid),
httpd_request_handler:socket_ownership_transfered(Pid, SocketType, Socket).
-handle_error(timeout, _) ->
+handle_error(timeout, _,_) ->
ok;
-handle_error({enfile, _}, _) ->
+handle_error({enfile, _}, _, _) ->
%% Out of sockets...
sleep(200);
-handle_error(emfile, _) ->
+handle_error(emfile, _, _) ->
%% Too many open files -> Out of sockets...
sleep(200);
-handle_error(closed, _) ->
+handle_error(closed, _, _) ->
error_logger:info_report("The httpd accept socket was closed by "
"a third party. "
"This will not have an impact on inets "
@@ -180,33 +156,30 @@ handle_error(closed, _) ->
%% and is not a problem for the server, so we want
%% to terminate normal so that we can restart without any
%% error messages.
-handle_error(econnreset,_) ->
+handle_error(econnreset,_,_) ->
exit(normal);
-handle_error(econnaborted, _) ->
+handle_error(econnaborted, _,_) ->
ok;
-handle_error(esslaccept, _) ->
+handle_error(esslaccept, _, _) ->
%% The user has selected to cancel the installation of
%% the certifikate, This is not a real error, so we do
%% not write an error message.
ok;
-handle_error(Reason, ConfigDb) ->
- String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])),
- accept_failed(ConfigDb, String).
+handle_error(Reason, ConfigDb, Location) ->
+ accept_failed(ConfigDb, {accept_failed, Reason}, Location).
-spec accept_failed(ConfigDB :: term(),
- ReasonString :: string()) -> no_return().
-
-accept_failed(ConfigDb, String) ->
- error_logger:error_report(String),
- InitData = #init_data{peername = {0, "unknown"}},
- Info = #mod{config_db = ConfigDb, init_data = InitData},
- mod_log:error_log(Info, String),
- mod_disk_log:error_log(Info, String),
- exit({accept_failed, String}).
+ ReasonString :: string(), map()) -> no_return().
+
+accept_failed(ConfigDb, Reason, Location) ->
+ InitData = #init_data{peername = {0, "unknown"}, sockname = {0, "unknown"}},
+ ModData = #mod{config_db = ConfigDb, init_data = InitData},
+ httpd_util:error_log(ConfigDb, httpd_logger:error_report('TCP', Reason, ModData, Location)),
+ exit({accept_failed, Reason}).
sleep(T) -> receive after T -> ok end.
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index 9e54f2b2c5..d42fc7c607 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -56,21 +56,16 @@
%% Phase 1: Load
load(ConfigFile) ->
- ?hdrv("load config", [{config_file, ConfigFile}]),
case read_config_file(ConfigFile) of
{ok, Config} ->
- ?hdrt("config read", []),
case bootstrap(Config) of
{error, Reason} ->
- ?hdri("bootstrap failed", [{reason, Reason}]),
{error, Reason};
{ok, Modules} ->
- ?hdrd("config bootstrapped", [{modules, Modules}]),
load_config(Config, lists:append(Modules, [?MODULE]))
end;
{error, Reason} ->
- ?hdri("failed reading config file", [{reason, Reason}]),
- {error, ?NICE("Error while reading config file: "++Reason)}
+ {error, ?NICE("Error while reading config file: "++Reason)}
end.
load(eof, []) ->
@@ -151,37 +146,25 @@ load("BindAddress " ++ Address0, []) ->
try
begin
- ?hdrv("load BindAddress", [{address0, Address0}]),
{Address, IpFamily} =
case string:tokens(Address0, [$|]) of
[Address1] ->
- ?hdrv("load BindAddress", [{address1, Address1}]),
{clean_address(Address1), inet};
[Address1, IpFamilyStr] ->
- ?hdrv("load BindAddress",
- [{address1, Address1},
- {ipfamily_str, IpFamilyStr}]),
- {clean_address(Address1), make_ipfamily(IpFamilyStr)};
+ {clean_address(Address1), make_ipfamily(IpFamilyStr)};
_Bad ->
- ?hdrv("load BindAddress - bad address",
- [{bad_address, _Bad}]),
- throw({error, {bad_bind_address, Address0}})
+ throw({error, {bad_bind_address, Address0}})
end,
- ?hdrv("load BindAddress - address and ipfamily separated",
- [{address, Address}, {ipfamily, IpFamily}]),
-
case Address of
"*" ->
{ok, [], [{bind_address, any}, {ipfamily, IpFamily}]};
_ ->
case httpd_util:ip_address(Address, IpFamily) of
{ok, IPAddr} ->
- ?hdrv("load BindAddress - checked",
- [{ip_address, IPAddr}]),
- Entries = [{bind_address, IPAddr},
- {ipfamily, IpFamily}],
- {ok, [], Entries};
+ Entries = [{bind_address, IPAddr},
+ {ipfamily, IpFamily}],
+ {ok, [], Entries};
{error, _} ->
{error, ?NICE(Address ++ " is an invalid address")}
end
@@ -189,11 +172,9 @@ load("BindAddress " ++ Address0, []) ->
end
catch
throw:{error, {bad_bind_address, _}} ->
- ?hdrv("load BindAddress - bad bind address", []),
{error, ?NICE(Address0 ++ " is an invalid address")};
throw:{error, {bad_ipfamily, _}} ->
- ?hdrv("load BindAddress - bad ipfamily", []),
- {error, ?NICE(Address0 ++ " has an invalid ipfamily")}
+ {error, ?NICE(Address0 ++ " has an invalid ipfamily")}
end;
load("KeepAlive " ++ OnorOff, []) ->
@@ -592,6 +573,12 @@ validate_config_params([{default_type, Value} | Rest]) when is_list(Value) ->
validate_config_params([{default_type, Value} | _]) ->
throw({default_type, Value});
+validate_config_params([{logger, Value} | Rest]) when is_list(Value) ->
+ true = validate_logger(Value),
+ validate_config_params(Rest);
+validate_config_params([{logger, Value} | _]) ->
+ throw({logger, Value});
+
validate_config_params([{ssl_certificate_file = Key, Value} | Rest]) ->
ok = httpd_util:file_validate(Key, Value),
validate_config_params(Rest);
@@ -671,12 +658,10 @@ is_bind_address(Value, IpFamily) ->
end.
store(ConfigList0) ->
- ?hdrd("store", []),
try validate_config_params(ConfigList0) of
ok ->
Modules =
proplists:get_value(modules, ConfigList0, ?DEFAULT_MODS),
- ?hdrt("store", [{modules, Modules}]),
Port = proplists:get_value(port, ConfigList0),
Addr = proplists:get_value(bind_address, ConfigList0, any),
Profile = proplists:get_value(profile, ConfigList0, default),
@@ -688,8 +673,6 @@ store(ConfigList0) ->
ConfigList)
catch
throw:Error ->
- ?hdri("store - config parameter validation failed",
- [{error, Error}]),
{error, {invalid_option, Error}}
end.
@@ -907,11 +890,9 @@ load_config(Config, Modules) ->
load_config(Config, Modules, Contexts, []).
load_config([], _Modules, _Contexts, ConfigList) ->
- ?hdrv("config loaded", []),
{ok, ConfigList};
load_config([Line|Config], Modules, Contexts, ConfigList) ->
- ?hdrt("load config", [{config_line, Line}]),
case load_traverse(Line, Contexts, Modules, [], ConfigList, no) of
{ok, NewContexts, NewConfigList} ->
load_config(Config, Modules, NewContexts, NewConfigList);
@@ -935,17 +916,12 @@ load_traverse(_Line, [], [], NewContexts, ConfigList, yes) ->
{ok, lists:reverse(NewContexts), ConfigList};
load_traverse(Line, [Context|Contexts], [Module|Modules], NewContexts,
ConfigList, State) ->
- ?hdrt("load config traverse",
- [{context, Context}, {httpd_module, Module}, {state, State}]),
case catch apply(Module, load, [Line, Context]) of
{'EXIT', {function_clause, _FC}} ->
- ?hdrt("does not handle load config",
- [{config_line, Line}, {fc, _FC}]),
load_traverse(Line, Contexts, Modules,
[Context|NewContexts], ConfigList, State);
{'EXIT', {undef, _}} ->
- ?hdrt("does not implement load", []),
load_traverse(Line, Contexts, Modules,
[Context|NewContexts], ConfigList, yes);
@@ -955,30 +931,23 @@ load_traverse(Line, [Context|Contexts], [Module|Modules], NewContexts,
[Context|NewContexts], ConfigList, State);
ok ->
- ?hdrt("line processed", []),
load_traverse(Line, Contexts, Modules,
[Context|NewContexts], ConfigList, yes);
{ok, NewContext} ->
- ?hdrt("line processed", [{new_context, NewContext}]),
load_traverse(Line, Contexts, Modules,
[NewContext|NewContexts], ConfigList, yes);
{ok, NewContext, ConfigEntry} when is_tuple(ConfigEntry) ->
- ?hdrt("line processed",
- [{new_context, NewContext}, {config_entry, ConfigEntry}]),
load_traverse(Line, Contexts,
Modules, [NewContext|NewContexts],
[ConfigEntry|ConfigList], yes);
{ok, NewContext, ConfigEntry} when is_list(ConfigEntry) ->
- ?hdrt("line processed",
- [{new_context, NewContext}, {config_entry, ConfigEntry}]),
load_traverse(Line, Contexts, Modules, [NewContext|NewContexts],
lists:append(ConfigEntry, ConfigList), yes);
{error, Reason} ->
- ?hdrv("line processing failed", [{reason, Reason}]),
{error, Reason}
end.
@@ -1063,7 +1032,6 @@ suffixes(MimeType,[Suffix|Rest]) ->
store(ConfigDB, _ConfigList, _Modules, []) ->
{ok, ConfigDB};
store(ConfigDB, ConfigList, Modules, [ConfigListEntry|Rest]) ->
- ?hdrt("store", [{entry, ConfigListEntry}]),
case store_traverse(ConfigListEntry, ConfigList, Modules) of
{ok, ConfigDBEntry} when is_tuple(ConfigDBEntry) ->
ets:insert(ConfigDB, ConfigDBEntry),
@@ -1080,20 +1048,15 @@ store(ConfigDB, ConfigList, Modules, [ConfigListEntry|Rest]) ->
store_traverse(_ConfigListEntry, _ConfigList,[]) ->
{error, ?NICE("Unable to store configuration...")};
store_traverse(ConfigListEntry, ConfigList, [Module|Rest]) ->
- ?hdrt("store traverse",
- [{httpd_module, Module}, {entry, ConfigListEntry}]),
case catch apply(Module, store, [ConfigListEntry, ConfigList]) of
{'EXIT',{function_clause,_}} ->
- ?hdrt("does not handle store config", []),
store_traverse(ConfigListEntry,ConfigList,Rest);
{'EXIT',{undef, _}} ->
- ?hdrt("does not implement store", []),
store_traverse(ConfigListEntry,ConfigList,Rest);
{'EXIT', Reason} ->
error_logger:error_report({'EXIT',Reason}),
store_traverse(ConfigListEntry,ConfigList,Rest);
Result ->
- ?hdrt("config entry processed", [{result, Result}]),
Result
end.
@@ -1223,6 +1186,10 @@ white_space_clean(String) ->
re:replace(String, "^[ \t\n\r\f]*|[ \t\n\r\f]*\$","",
[{return,list}, global]).
+validate_logger([{error, Domain}]) when is_atom(Domain) ->
+ true;
+validate_logger(List) ->
+ throw({logger, List}).
%%%=========================================================================
%%% Deprecated remove in 19
diff --git a/lib/inets/src/http_server/httpd_internal.hrl b/lib/inets/src/http_server/httpd_internal.hrl
index 09d720ee85..dfe9f1fa9f 100644
--- a/lib/inets/src/http_server/httpd_internal.hrl
+++ b/lib/inets/src/http_server/httpd_internal.hrl
@@ -41,38 +41,4 @@
{sizefmt,"abbrev"}]).
--ifdef(inets_error).
--define(ERROR(Format, Args), io:format("E(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(ERROR(F,A),[]).
--endif.
-
--ifdef(inets_log).
--define(LOG(Format, Args), io:format("L(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(LOG(F,A),[]).
--endif.
-
--ifdef(inets_debug).
--define(DEBUG(Format, Args), io:format("D(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(DEBUG(F,A),[]).
--endif.
-
--ifdef(inets_cdebug).
--define(CDEBUG(Format, Args), io:format("C(~p:~p:~p) : "++Format++"~n",
- [self(),?MODULE,?LINE]++Args)).
--else.
--define(CDEBUG(F,A),[]).
--endif.
-
--define(SERVICE, httpd).
--define(hdri(Label, Content), ?report_important(Label, ?SERVICE, Content)).
--define(hdrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)).
--define(hdrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)).
--define(hdrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)).
-
-endif. % -ifdef(httpd_internal_hrl).
diff --git a/lib/inets/src/http_server/httpd_logger.erl b/lib/inets/src/http_server/httpd_logger.erl
new file mode 100644
index 0000000000..a9297dc26a
--- /dev/null
+++ b/lib/inets/src/http_server/httpd_logger.erl
@@ -0,0 +1,143 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+-module(httpd_logger).
+
+-include_lib("kernel/include/logger.hrl").
+-include_lib("inets/include/httpd.hrl").
+
+-export([error_report/4, log/3, format/1]).
+
+error_report(Protocol, Reason, #mod{init_data = #init_data{peername = PeerName,
+ sockname = SockName},
+ socket_type = Type,
+ request_uri = URI,
+ config_db = Db},
+ Location) ->
+ ServerName = httpd_util:lookup(Db, server_name),
+ Report0 = #{protocol => Protocol,
+ reason => Reason,
+ peer => PeerName,
+ host => SockName,
+ server_name => ServerName,
+ metadata => Location},
+ Report1 = case URI of
+ undefined ->
+ Report0;
+ _ ->
+ Report0#{uri => URI}
+ end,
+ case Protocol of
+ 'HTTP' ->
+ Report1#{transport => transport_type(Type)};
+ _ ->
+ Report1
+ end.
+
+log(Level, #{metadata := MetaData} = Report, Domain) ->
+ logger:log(Level, maps:without([metadata], Report),
+ MetaData#{domain => [otp,inets, httpd, Domain, Level],
+ report_cb => fun ?MODULE:format/1}).
+
+format(#{protocol := Protocol} = Report) when Protocol == 'TLS';
+ Protocol == 'TCP' ->
+ #{reason := Desc,
+ peer := {PeerPort, Peer},
+ host := {HostPort, Host},
+ server_name := ServerName
+ } = Report,
+ {
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s:~p~n"
+ "~10s ~s:~p~n"
+ "~10s ~p~n"
+ "~n",
+ ["Server:", ServerName,
+ "Protocol:", atom_to_list(Protocol),
+ "Host:", Host, HostPort,
+ "Peer:", Peer, PeerPort,
+ "Reason:", Desc]
+ };
+format(#{protocol := 'HTTP' = Protocol, uri := URI} = Report) ->
+ #{reason := Desc,
+ transport := Transport,
+ peer := {PeerPort, Peer},
+ host := {HostPort, Host},
+ server_name := ServerName} = Report,
+ {
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s:~p~n"
+ "~10s ~s:~p~n"
+ "~10s ~p~n"
+ "~n",
+ ["Server:", ServerName,
+ "Protocol:", atom_to_list(Protocol),
+ "Transport:", Transport,
+ "URI:", URI,
+ "Host:", Host, HostPort,
+ "Peer:", Peer, PeerPort,
+ "Reason:", Desc]
+ };
+format(#{protocol := 'HTTP' = Protocol} = Report) ->
+ #{reason := Desc,
+ transport := Transport,
+ peer := {PeerPort, Peer},
+ host := {HostPort, Host},
+ server_name := ServerName} = Report,
+ {
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s:~p~n"
+ "~10s ~s:~p~n"
+ "~10s ~p~n"
+ "~n",
+ ["Server:", ServerName,
+ "Protocol:", atom_to_list(Protocol),
+ "Transport:", Transport,
+ "Host:", Host, HostPort,
+ "Peer:", Peer, PeerPort,
+ "Reason:", Desc]
+ };
+format(#{protocol := internal = Protocol} = Report) ->
+ #{reason := Desc,
+ host := {HostPort, Host},
+ server_name := ServerName
+ } = Report,
+ {
+ "~10s ~s~n"
+ "~10s ~s~n"
+ "~10s ~s:~p~n"
+ "~10s ~p~n"
+ "~n",
+ ["Server:", ServerName,
+ "Protocol:", atom_to_list(Protocol),
+ "Host:", Host, HostPort,
+ "Reason:", Desc]
+ }.
+
+transport_type(ip_comm) ->
+ "TCP";
+transport_type(_) ->
+ "TLS".
diff --git a/lib/inets/src/http_server/httpd_request.erl b/lib/inets/src/http_server/httpd_request.erl
index 9d7538a13d..0690102b58 100644
--- a/lib/inets/src/http_server/httpd_request.erl
+++ b/lib/inets/src/http_server/httpd_request.erl
@@ -44,10 +44,8 @@
%%% Internal application API
%%%=========================================================================
parse([Bin, Options]) ->
- ?hdrt("parse", [{bin, Bin}, {max_sizes, Options}]),
parse_method(Bin, [], 0, proplists:get_value(max_method, Options), Options, []);
parse(Unknown) ->
- ?hdrt("parse", [{unknown, Unknown}]),
exit({bad_args, Unknown}).
%% Functions that may be returned during the decoding process
@@ -436,19 +434,13 @@ get_persistens(HTTPVersion,ParsedHeader,ConfigDB)->
%%older http/1.1 might be older Clients that
%%use it.
"keep-alive" when hd(NList) >= 49 ->
- ?DEBUG("CONNECTION MODE: ~p",[true]),
true;
"close" ->
- ?DEBUG("CONNECTION MODE: ~p",[false]),
- false;
+ false;
_Connect ->
- ?DEBUG("CONNECTION MODE: ~p VALUE: ~p",
- [false, _Connect]),
- false
+ false
end;
_ ->
- ?DEBUG("CONNECTION MODE: ~p VERSION: ~p",
- [false, HTTPVersion]),
false
end;
_ ->
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index d918f10424..e48555f4d7 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -34,7 +34,7 @@
-include("httpd.hrl").
-include("http_internal.hrl").
--include("httpd_internal.hrl").
+-include_lib("kernel/include/logger.hrl").
-define(HANDSHAKE_TIMEOUT, 5000).
@@ -100,21 +100,39 @@ init([Manager, ConfigDB, AcceptTimeout]) ->
{SocketType, Socket} = await_socket_ownership_transfer(AcceptTimeout),
+ Peername = http_transport:peername(SocketType, Socket),
+ Sockname = http_transport:sockname(SocketType, Socket),
+
%%Timeout value is in seconds we want it in milliseconds
KeepAliveTimeOut = 1000 * httpd_util:lookup(ConfigDB, keep_alive_timeout, 150),
case http_transport:negotiate(SocketType, Socket, ?HANDSHAKE_TIMEOUT) of
- {error, Error} ->
- exit({shutdown, Error}); %% Can be 'normal'.
- ok ->
- continue_init(Manager, ConfigDB, SocketType, Socket, KeepAliveTimeOut)
+ {error, {tls_alert, {_, AlertDesc}} = Error} ->
+ ModData = #mod{config_db = ConfigDB, init_data = #init_data{peername = Peername,
+ sockname = Sockname}},
+ httpd_util:error_log(ConfigDB, httpd_logger:error_report('TLS', AlertDesc,
+ ModData, ?LOCATION)),
+ exit({shutdown, Error});
+ {error, _Reason} = Error ->
+ %% This happens if the peer closes the connection
+ %% or the handshake is timed out. This is not
+ %% an error condition of the server and client will
+ %% retry in the timeout situation.
+ exit({shutdown, Error});
+ {ok, TLSSocket} ->
+ continue_init(Manager, ConfigDB, SocketType, TLSSocket,
+ Peername, Sockname, KeepAliveTimeOut);
+ ok ->
+ continue_init(Manager, ConfigDB, SocketType, Socket,
+ Peername, Sockname, KeepAliveTimeOut)
end.
-continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
+continue_init(Manager, ConfigDB, SocketType, Socket, Peername, Sockname,
+ TimeOut) ->
Resolve = http_transport:resolve(),
-
- Peername = httpd_socket:peername(SocketType, Socket),
- InitData = #init_data{peername = Peername, resolve = Resolve},
+ InitData = #init_data{peername = Peername,
+ sockname = Sockname,
+ resolve = Resolve},
Mod = #mod{config_db = ConfigDB,
socket_type = SocketType,
socket = Socket,
@@ -163,14 +181,11 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) ->
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
-handle_call(Request, From, #state{mod = ModData} = State) ->
- Error =
- lists:flatten(
- io_lib:format("Unexpected request: "
- "~n~p"
- "~nto request handler (~p) from ~p"
- "~n", [Request, self(), From])),
- error_log(Error, ModData),
+handle_call(Request, From, #state{mod = #mod{config_db = Db} = ModData} = State) ->
+ httpd_util:error_log(Db,
+ httpd_logger:error_report(internal,
+ [{unexpected_call, Request}, {to, self()}, {from, From}], ModData,
+ ?LOCATION)),
{stop, {call_api_violation, Request, From}, State}.
%%--------------------------------------------------------------------
@@ -179,14 +194,10 @@ handle_call(Request, From, #state{mod = ModData} = State) ->
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
-handle_cast(Msg, #state{mod = ModData} = State) ->
- Error =
- lists:flatten(
- io_lib:format("Unexpected message: "
- "~n~p"
- "~nto request handler (~p)"
- "~n", [Msg, self()])),
- error_log(Error, ModData),
+handle_cast(Msg, #state{mod = #mod{config_db = Db} = ModData} = State) ->
+ httpd_util:error_log(Db,
+ httpd_logger:error_report(internal, [{unexpected_cast, Msg}, {to, self()}], ModData,
+ ?LOCATION)),
{noreply, State}.
%%--------------------------------------------------------------------
@@ -223,10 +234,7 @@ handle_info({Proto, Socket, Data},
handle_msg(Result, NewState);
{error, {size_error, MaxSize, ErrCode, ErrStr}, Version} ->
NewModData = ModData#mod{http_version = Version},
- httpd_response:send_status(NewModData, ErrCode, ErrStr),
- Reason = io_lib:format("~p: ~p max size is ~p~n",
- [ErrCode, ErrStr, MaxSize]),
- error_log(Reason, NewModData),
+ httpd_response:send_status(NewModData, ErrCode, ErrStr, {max_size, MaxSize}),
{stop, normal, State#state{response_sent = true,
mod = NewModData}};
@@ -255,14 +263,12 @@ handle_info({ssl_error, _, _} = Reason, State) ->
%% Timeouts
handle_info(timeout, #state{mfa = {_, parse, _}} = State) ->
- %% error_log("No request received on keep-alive connection "
- %% "before server side timeout", ModData),
- %% No response should be sent!
+ %% No request received on keep-alive connection
+ %% before server side timeout. No response should be sent!
{stop, normal, State#state{response_sent = true}};
handle_info(timeout, #state{mod = ModData} = State) ->
- httpd_response:send_status(ModData, 408, "Request timeout"),
- error_log("The client did not send the whole request before the "
- "server side timeout", ModData),
+ httpd_response:send_status(ModData, 408, "Request timeout", "The client did not send the whole request before the "
+ "server side timeout"),
{stop, normal, State#state{response_sent = true}};
handle_info(check_data_first, #state{data = Data, byte_limit = Byte_Limit} = State) ->
case Data >= (Byte_Limit*3) of
@@ -285,13 +291,11 @@ handle_info({'EXIT', _, Reason}, State) ->
{stop, Reason, State};
%% Default case
-handle_info(Info, #state{mod = ModData} = State) ->
- Error = lists:flatten(
- io_lib:format("Unexpected info: "
- "~n~p"
- "~nto request handler (~p)"
- "~n", [Info, self()])),
- error_log(Error, ModData),
+handle_info(Info, #state{mod = #mod{config_db = Db} =ModData} = State) ->
+ httpd_util:error_log(Db,
+ httpd_logger:error_report(internal,
+ [{unexpected_info, Info}, {to, self()}], ModData,
+ ?LOCATION)),
{noreply, State}.
@@ -310,10 +314,6 @@ terminate({shutdown,_}, State) ->
do_terminate(State);
terminate(Reason, #state{response_sent = false, mod = ModData} = State) ->
httpd_response:send_status(ModData, 500, none),
- ReasonStr =
- lists:flatten(io_lib:format("~s - ~p",
- [httpd_util:reason_phrase(500), Reason])),
- error_log(ReasonStr, ModData),
terminate(Reason, State#state{response_sent = true, mod = ModData});
terminate(_Reason, State) ->
do_terminate(State).
@@ -419,26 +419,18 @@ handle_http_msg({Method, Uri, Version, {RecordHeaders, Headers}, Body},
end;
{error, {not_supported, What}} ->
httpd_response:send_status(ModData#mod{http_version = Version},
- 501, {Method, Uri, Version}),
- Reason = io_lib:format("Not supported: ~p~n", [What]),
- error_log(Reason, ModData),
+ 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),
- Reason = io_lib:format("Forbidden URI: ~p~n", [URI]),
- error_log(Reason, ModData),
{stop, normal, State#state{response_sent = true}};
{error, {bad_request, {malformed_syntax, URI}}} ->
httpd_response:send_status(ModData#mod{http_version = Version},
- 400, URI),
- Reason = io_lib:format("Malformed syntax in URI: ~p~n", [URI]),
- error_log(Reason, ModData),
+ 400, URI, {malformed_syntax, URI}),
{stop, normal, State#state{response_sent = true}};
{error, {bad_version, Ver}} ->
- httpd_response:send_status(ModData#mod{http_version = "HTTP/0.9"}, 400, Ver),
- Reason = io_lib:format("Malformed syntax version: ~p~n", [Ver]),
- error_log(Reason, ModData),
+ httpd_response:send_status(ModData#mod{http_version = "HTTP/0.9"}, 400, Ver, {malformed_syntax, Ver}),
{stop, normal, State#state{response_sent = true}}
end;
handle_http_msg(Body, State) ->
@@ -497,18 +489,13 @@ handle_body(#state{headers = Headers, body = Body,
catch
throw:Error ->
httpd_response:send_status(ModData, 400,
- "Bad input"),
- Reason = io_lib:format("Chunk decoding failed: ~p~n",
- [Error]),
- error_log(Reason, ModData),
+ "Bad input", {chunk_decoding, bad_input, Error}),
{stop, normal, State#state{response_sent = true}}
end;
Encoding when is_list(Encoding) ->
httpd_response:send_status(ModData, 501,
- "Unknown Transfer-Encoding"),
- Reason = io_lib:format("Unknown Transfer-Encoding: ~p~n",
- [Encoding]),
- error_log(Reason, ModData),
+ "Unknown Transfer-Encoding",
+ {unknown_transfer_encoding, Encoding}),
{stop, normal, State#state{response_sent = true}};
_ ->
Length = list_to_integer(Headers#http_request_h.'content-length'),
@@ -544,7 +531,6 @@ handle_body(#state{headers = Headers, body = Body,
end;
false ->
httpd_response:send_status(ModData, 413, "Body too long"),
- error_log("Body too long", ModData),
{stop, normal, State#state{response_sent = true}}
end
end.
@@ -559,22 +545,21 @@ handle_expect(#state{headers = Headers, mod =
ok;
continue when MaxBodySize < Length ->
httpd_response:send_status(ModData, 413, "Body too long"),
- error_log("Body too long", ModData),
{stop, normal, State#state{response_sent = true}};
{break, Value} ->
httpd_response:send_status(ModData, 417,
- "Unexpected expect value"),
- Reason = io_lib:format("Unexpected expect value: ~p~n", [Value]),
- error_log(Reason, ModData),
+ "Unexpected expect value",
+ {unexpected, Value}
+ ),
{stop, normal, State#state{response_sent = true}};
no_expect_header ->
ok;
http_1_0_expect_header ->
httpd_response:send_status(ModData, 400,
"Only HTTP/1.1 Clients "
- "may use the Expect Header"),
- error_log("Client with lower version than 1.1 tried to send"
- "an expect header", ModData),
+ "may use the Expect Header",
+ "Client with lower version than 1.1 tried to send"
+ "an expect header"),
{stop, normal, State#state{response_sent = true}}
end.
@@ -732,13 +717,7 @@ decrease(N) when is_integer(N) ->
decrease(N) ->
N.
-error_log(ReasonString, #mod{config_db = ConfigDB}) ->
- Error = lists:flatten(
- io_lib:format("Error reading request: ~s", [ReasonString])),
- httpd_util:error_log(ConfigDB, Error).
-
-
-%%--------------------------------------------------------------------
+%--------------------------------------------------------------------
%% Config access wrapper functions
%%--------------------------------------------------------------------
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index bb946664f9..7b204e12ad 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -19,7 +19,7 @@
%%
%%
-module(httpd_response).
--export([generate_and_send_response/1, send_status/3, send_header/3,
+-export([generate_and_send_response/1, send_status/3, send_status/4, send_header/3,
send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3,
split_header/2, is_disable_chunked_send/1, cache_headers/2, handle_continuation/1]).
-export([map_status_code/2]).
@@ -28,6 +28,7 @@
-include_lib("inets/include/httpd.hrl").
-include_lib("inets/src/http_lib/http_internal.hrl").
-include_lib("inets/src/http_server/httpd_internal.hrl").
+-include_lib("kernel/include/logger.hrl").
-define(VMODULE,"RESPONSE").
@@ -48,7 +49,7 @@ generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
ok;
{proceed, Data} ->
case proplists:get_value(status, Data) of
- {StatusCode, PhraseArgs, _Reason} ->
+ {StatusCode, PhraseArgs, _Reason} ->
send_status(ModData, StatusCode, PhraseArgs),
ok;
undefined ->
@@ -89,14 +90,12 @@ traverse_modules(ModData,[Module|Rest]) ->
traverse_modules(ModData#mod{data = NewData}, Rest)
catch
T:E:Stacktrace ->
- String =
- lists:flatten(
- io_lib:format("module traverse failed: ~p:do => "
- "~n Error Type: ~p"
- "~n Error: ~p"
- "~n Stack trace: ~p",
- [Module, T, E, Stacktrace])),
- httpd_util:error_log(ModData#mod.config_db, String),
+ httpd_util:error_log(ModData#mod.config_db,
+ httpd_logger:error_report('HTTP',
+ [{module, Module},
+ {class, T},
+ {error, E},
+ {stacktrace, Stacktrace}], ModData, ?LOCATION)),
send_status(ModData, 500, none),
done
end.
@@ -107,9 +106,12 @@ traverse_modules(ModData,[Module|Rest]) ->
send_status(ModData, 100, _PhraseArgs) ->
send_header(ModData, 100, [{content_length, "0"}]);
+send_status(ModData, StatusCode, PhraseArgs) ->
+ send_status(ModData, StatusCode, PhraseArgs, undefined).
+
send_status(#mod{socket_type = SocketType,
socket = Socket,
- config_db = ConfigDB} = ModData, StatusCode, PhraseArgs) ->
+ config_db = ConfigDB} = ModData, StatusCode, PhraseArgs, Details) ->
ReasonPhrase = httpd_util:reason_phrase(StatusCode),
Message = httpd_util:message(StatusCode, PhraseArgs, ConfigDB),
@@ -119,6 +121,21 @@ send_status(#mod{socket_type = SocketType,
[{content_type, "text/html"},
{content_length, integer_to_list(length(Body))}]),
+ if StatusCode >= 400 ->
+ case Details of
+ undefined ->
+ httpd_util:error_log(ConfigDB, httpd_logger:error_report('HTTP',
+ [{statuscode, StatusCode}, {description, ReasonPhrase}],
+ ModData, ?LOCATION));
+ _ ->
+ httpd_util:error_log(ConfigDB, httpd_logger:error_report('HTTP',
+ [{statuscode,StatusCode}, {description, ReasonPhrase},
+ {details, Details}], ModData,
+ ?LOCATION))
+ end;
+ true ->
+ ok
+ end,
httpd_socket:deliver(SocketType, Socket, Body).
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 4a2eff4770..6b3b2c9660 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -35,6 +35,7 @@
-export([encode_hex/1, decode_hex/1]).
-include_lib("kernel/include/file.hrl").
+-include_lib("inets/include/httpd.hrl").
ip_address({_,_,_,_} = Address, _IpFamily) ->
{ok, Address};
@@ -762,16 +763,33 @@ do_enable_debug([{Level,Modules}|Rest])
end,
do_enable_debug(Rest).
-error_log(ConfigDb, Error) ->
- error_log(mod_log, ConfigDb, Error),
- error_log(mod_disk_log, ConfigDb, Error).
-
-error_log(Mod, ConfigDB, Error) ->
+
+error_log(ConfigDB, Report) ->
+ case lookup(ConfigDB, logger) of
+ undefined ->
+ mod_error_logging(mod_log, ConfigDB, Report),
+ mod_error_logging(mod_disk_log, ConfigDB, Report);
+ Logger ->
+ Domain = proplists:get_value(error, Logger),
+ httpd_logger:log(error, Report, Domain),
+ %% Backwards compat
+ mod_error_logging(mod_log, ConfigDB, Report),
+ mod_error_logging(mod_disk_log, ConfigDB, Report)
+ end.
+
+mod_error_logging(Mod, ConfigDB, Report) ->
Modules = httpd_util:lookup(ConfigDB, modules,
[mod_get, mod_head, mod_log]),
case lists:member(Mod, Modules) of
true ->
- Mod:report_error(ConfigDB, Error);
+ %% Make it oneline string for backwards compatibility
+ Msg = httpd_logger:format(Report),
+ ErrorStr = lists:flatten(logger_formatter:format(#{level => error,
+ msg => Msg,
+ meta => #{}
+ },
+ #{template => [msg]})),
+ Mod:report_error(ConfigDB, ErrorStr);
_ ->
ok
end.
diff --git a/lib/inets/src/http_server/mod_alias.erl b/lib/inets/src/http_server/mod_alias.erl
index 68a3de0229..fac59ab93c 100644
--- a/lib/inets/src/http_server/mod_alias.erl
+++ b/lib/inets/src/http_server/mod_alias.erl
@@ -37,7 +37,6 @@
%% do
do(#mod{data = Data} = Info) ->
- ?hdrt("do", []),
case proplists:get_value(status, Data) of
%% A status code has been generated!
{_StatusCode, _PhraseArgs, _Reason} ->
@@ -60,17 +59,11 @@ do_alias(#mod{config_db = ConfigDB,
data = Data}) ->
{ShortPath, Path, AfterPath} =
real_name(ConfigDB, ReqURI, which_alias(ConfigDB)),
- ?hdrt("real name",
- [{request_uri, ReqURI},
- {short_path, ShortPath},
- {path, Path},
- {after_path, AfterPath}]),
%% Relocate if a trailing slash is missing else proceed!
LastChar = lists:last(ShortPath),
case file:read_file_info(ShortPath) of
{ok, FileInfo} when ((FileInfo#file_info.type =:= directory) andalso
(LastChar =/= $/)) ->
- ?hdrt("directory and last-char is a /", []),
ServerName = which_server_name(ConfigDB),
Port = port_string(which_port(ConfigDB)),
Protocol = get_protocol(SocketType),
diff --git a/lib/inets/src/http_server/mod_dir.erl b/lib/inets/src/http_server/mod_dir.erl
index ba93d0b271..2a90575e7d 100644
--- a/lib/inets/src/http_server/mod_dir.erl
+++ b/lib/inets/src/http_server/mod_dir.erl
@@ -28,7 +28,6 @@
%% do
do(Info) ->
- ?DEBUG("do -> entry",[]),
case Info#mod.method of
"GET" ->
case proplists:get_value(status, Info#mod.data) of
@@ -52,7 +51,6 @@ do(Info) ->
end.
do_dir(Info) ->
- ?DEBUG("do_dir -> Request URI: ~p",[Info#mod.request_uri]),
Path = mod_alias:path(Info#mod.data,Info#mod.config_db,
Info#mod.request_uri),
DefaultPath = mod_alias:default_index(Info#mod.config_db,Path),
@@ -61,11 +59,6 @@ do_dir(Info) ->
{ok,FileInfo} when FileInfo#file_info.type == directory ->
DecodedRequestURI =
http_uri:decode(Info#mod.request_uri),
- ?DEBUG("do_dir -> ~n"
- " Path: ~p~n"
- " DefaultPath: ~p~n"
- " DecodedRequestURI: ~p",
- [Path,DefaultPath,DecodedRequestURI]),
case dir(DefaultPath,string:strip(DecodedRequestURI,right,$/),
Info#mod.config_db) of
{ok, Dir} ->
@@ -85,21 +78,13 @@ do_dir(Info) ->
{proceed,[{response,{response, Head, Dir}},
{mime_type,"text/html"} | Info#mod.data]};
{error, Reason} ->
- ?ERROR("do_dir -> dir operation failed: ~p",[Reason]),
{proceed,
[{status,{404,Info#mod.request_uri,Reason}}|
Info#mod.data]}
end;
{ok, _FileInfo} ->
- ?DEBUG("do_dir -> ~n"
- " Path: ~p~n"
- " DefaultPath: ~p~n"
- " FileInfo: ~p",
- [Path,DefaultPath,FileInfo]),
{proceed,Info#mod.data};
{error,Reason} ->
- ?LOG("do_dir -> failed reading file info (~p) for: ~p",
- [Reason,DefaultPath]),
Status = httpd_file:handle_error(Reason, "access", Info,
DefaultPath),
{proceed, [{status, Status}| Info#mod.data]}
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index bcf392d55c..112e74575d 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -31,6 +31,7 @@
-include("httpd.hrl").
-include("httpd_internal.hrl").
+-include_lib("kernel/include/logger.hrl").
-define(VMODULE,"ESI").
-define(DEFAULT_ERL_TIMEOUT,15).
@@ -464,8 +465,9 @@ handle_body(Pid, ModData, Body, Timeout, Size, StatusCode, IsDisableChunkedSend)
{proceed, [{response, {already_sent, StatusCode, Size}} |
ModData#mod.data]};
{'EXIT', Pid, Reason} when is_pid(Pid) ->
- Error = lists:flatten(io_lib:format("mod_esi process failed with reason ~p", [Reason])),
- httpd_util:error_log(ModData#mod.config_db, Error),
+ httpd_util:error_log(ModData#mod.config_db,
+ httpd_logger:error_report('HTTP',
+ [{mod_esi, Reason}], ModData, ?LOCATION)),
httpd_response:send_final_chunk(ModData,
[{"Warning", "199 inets server - body maybe incomplete, "
"internal server error"}],
diff --git a/lib/inets/src/http_server/mod_get.erl b/lib/inets/src/http_server/mod_get.erl
index 58600f5e3e..f615e8d3fa 100644
--- a/lib/inets/src/http_server/mod_get.erl
+++ b/lib/inets/src/http_server/mod_get.erl
@@ -32,7 +32,6 @@
%% do
do(Info) ->
- ?DEBUG("do -> entry",[]),
case Info#mod.method of
"GET" ->
case proplists:get_value(status, Info#mod.data) of
@@ -57,7 +56,6 @@ do(Info) ->
do_get(Info) ->
- ?DEBUG("do_get -> Request URI: ~p",[Info#mod.request_uri]),
Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
Info#mod.request_uri),
@@ -71,7 +69,6 @@ send_response(_Socket, _SocketType, Path, Info)->
case file:open(Path,[raw,binary]) of
{ok, FileDescriptor} ->
{FileInfo, LastModified} = get_modification_date(Path),
- ?DEBUG("do_get -> FileDescriptor: ~p",[FileDescriptor]),
Suffix = httpd_util:suffix(Path),
MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,
Suffix,"text/plain"),
@@ -94,8 +91,6 @@ send_response(_Socket, _SocketType, Path, Info)->
FileInfo#file_info.size}},
{mime_type,MimeType} | Info#mod.data]};
{error, Reason} ->
- ?hdrt("send_response -> failed open file",
- [{path, Path}, {reason, Reason}]),
Status = httpd_file:handle_error(Reason, "open", Info, Path),
{proceed, [{status, Status} | Info#mod.data]}
end.
@@ -104,7 +99,6 @@ send_response(_Socket, _SocketType, Path, Info)->
send(#mod{socket = Socket, socket_type = SocketType} = Info,
StatusCode, Headers, FileDescriptor) ->
- ?DEBUG("send -> send header",[]),
httpd_response:send_header(Info, StatusCode, Headers),
send_body(SocketType,Socket,FileDescriptor).
@@ -112,16 +106,13 @@ send(#mod{socket = Socket, socket_type = SocketType} = Info,
send_body(SocketType,Socket,FileDescriptor) ->
case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
{ok,Binary} ->
- ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
case httpd_socket:deliver(SocketType,Socket,Binary) of
socket_closed ->
- ?LOG("send_body -> socket closed while sending",[]),
socket_close;
_ ->
send_body(SocketType,Socket,FileDescriptor)
end;
eof ->
- ?DEBUG("send_body -> done with this file",[]),
eof
end.
diff --git a/lib/inets/src/http_server/mod_range.erl b/lib/inets/src/http_server/mod_range.erl
index 1c6c6d927d..36ccdc268a 100644
--- a/lib/inets/src/http_server/mod_range.erl
+++ b/lib/inets/src/http_server/mod_range.erl
@@ -25,7 +25,6 @@
%% do
do(Info) ->
- ?DEBUG("do -> entry",[]),
case Info#mod.method of
"GET" ->
case proplists:get_value(status, Info#mod.data) of
@@ -66,7 +65,6 @@ do(Info) ->
end.
do_get_range(Info,Ranges) ->
- ?DEBUG("do_get_range -> Request URI: ~p",[Info#mod.request_uri]),
Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
Info#mod.request_uri),
{FileInfo, LastModified} = get_modification_date(Path),
@@ -76,7 +74,6 @@ do_get_range(Info,Ranges) ->
send_range_response(Path, Info, Ranges, FileInfo, LastModified)->
case parse_ranges(Ranges) of
error->
- ?ERROR("send_range_response-> Unparsable range request",[]),
{proceed,Info#mod.data};
{multipart,RangeList}->
send_multi_range_response(Path, Info, RangeList);
@@ -110,15 +107,12 @@ send_multi_range_response(Path,Info,RangeList)->
case file:open(Path, [raw,binary]) of
{ok, FileDescriptor} ->
file:close(FileDescriptor),
- ?DEBUG("send_multi_range_response -> FileDescriptor: ~p",
- [FileDescriptor]),
Suffix = httpd_util:suffix(Path),
PartMimeType = httpd_util:lookup_mime_default(Info#mod.config_db,
Suffix,"text/plain"),
{FileInfo, LastModified} = get_modification_date(Path),
case valid_ranges(RangeList,Path,FileInfo) of
{ValidRanges,true}->
- ?DEBUG("send_multi_range_response ->Ranges are valid:",[]),
%Apache breaks the standard by sending the size
%field in the Header.
Header =
@@ -127,8 +121,6 @@ send_multi_range_response(Path,Info,RangeList)->
"=RangeBoundarySeparator"},
{etag, httpd_util:create_etag(FileInfo)} |
LastModified],
- ?DEBUG("send_multi_range_response -> Valid Ranges: ~p",
- [RagneList]),
Body = {fun send_multiranges/4,
[ValidRanges, Info, PartMimeType, Path]},
{proceed,[{response,
@@ -138,12 +130,10 @@ send_multi_range_response(Path,Info,RangeList)->
bad_range_boundaries }}]}
end;
{error, _Reason} ->
- ?ERROR("do_get -> failed open file: ~p",[_Reason]),
{proceed,Info#mod.data}
end.
send_multiranges(ValidRanges,Info,PartMimeType,Path)->
- ?DEBUG("send_multiranges -> Start sending the ranges",[]),
case file:open(Path, [raw,binary]) of
{ok,FileDescriptor} ->
lists:foreach(fun(Range)->
@@ -195,8 +185,6 @@ send_range_response(Path, Info, Start, Stop, FileInfo, LastModified)->
case file:open(Path, [raw,binary]) of
{ok, FileDescriptor} ->
file:close(FileDescriptor),
- ?DEBUG("send_range_response -> FileDescriptor: ~p",
- [FileDescriptor]),
Suffix = httpd_util:suffix(Path),
MimeType = httpd_util:lookup_mime_default(Info#mod.config_db,
Suffix,"text/plain"),
@@ -219,13 +207,11 @@ send_range_response(Path, Info, Start, Stop, FileInfo, LastModified)->
{proceed, [{status, {416, Reason, bad_range_boundaries }}]}
end;
{error, _Reason} ->
- ?ERROR("send_range_response -> failed open file: ~p",[_Reason]),
{proceed,Info#mod.data}
end.
send_range_body(SocketType,Socket,Path,Start,End) ->
- ?DEBUG("mod_range -> send_range_body",[]),
case file:open(Path, [raw,binary]) of
{ok,FileDescriptor} ->
send_part_start(SocketType,Socket,FileDescriptor,Start,End),
@@ -268,8 +254,6 @@ send_part(SocketType,Socket,FileDescriptor,End)->
case httpd_socket:deliver(SocketType,Socket,
Binary) of
socket_closed ->
- ?LOG("send_range of body -> socket "
- "closed while sending",[]),
socket_close;
_ ->
send_part(SocketType,Socket,
@@ -406,15 +390,12 @@ split_range([N|Rest],Current,End) ->
send_body(SocketType,Socket,FileDescriptor) ->
case file:read(FileDescriptor,?FILE_CHUNK_SIZE) of
{ok,Binary} ->
- ?DEBUG("send_body -> send another chunk: ~p",[size(Binary)]),
case httpd_socket:deliver(SocketType,Socket,Binary) of
socket_closed ->
- ?LOG("send_body -> socket closed while sending",[]),
socket_close;
_ ->
send_body(SocketType,Socket,FileDescriptor)
end;
eof ->
- ?DEBUG("send_body -> done with this file",[]),
eof
end.
diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl
index 07129940a5..ca1bde519e 100644
--- a/lib/inets/src/http_server/mod_responsecontrol.erl
+++ b/lib/inets/src/http_server/mod_responsecontrol.erl
@@ -26,7 +26,6 @@
-include("httpd_internal.hrl").
do(Info) ->
- ?DEBUG("do -> response_control",[]),
case proplists:get_value(status, Info#mod.data) of
%% A status code has been generated!
{_StatusCode, _PhraseArgs, _Reason} ->
@@ -53,7 +52,6 @@ do(Info) ->
%%wheather a response shall be createed or not
%%----------------------------------------------------------------------
do_responsecontrol(Info) ->
- ?DEBUG("do_response_control -> Request URI: ~p",[Info#mod.request_uri]),
Path = mod_alias:path(Info#mod.data, Info#mod.config_db,
Info#mod.request_uri),
case file:read_file_info(Path) of
@@ -220,7 +218,6 @@ compare_etags(Tag,Etags) ->
%% Control the If-Modified-Since and If-Not-Modified-Since header fields
%%----------------------------------------------------------------------
control_modification(Path,Info,FileInfo)->
- ?DEBUG("control_modification() -> entry",[]),
case control_modification_data(Info,
FileInfo#file_info.mtime,
"if-modified-since") of
@@ -260,23 +257,18 @@ control_modification_data(Info, ModificationTime, HeaderField)->
bad_date ->
{bad_date, LastModified0};
ConvertedReqDate ->
- LastModified =
- calendar:universal_time_to_local_time(ConvertedReqDate),
- ?DEBUG("control_modification_data() -> "
- "~n Request-Field: ~s"
- "~n FileLastModified: ~p"
- "~n FieldValue: ~p",
- [HeaderField, ModificationTime, LastModified]),
- FileTime =
+ LastModified = calendar:universal_time_to_local_time(ConvertedReqDate),
+ FileTime =
calendar:datetime_to_gregorian_seconds(ModificationTime),
FieldTime =
calendar:datetime_to_gregorian_seconds(LastModified),
if
FileTime =< FieldTime ->
- ?DEBUG("File unmodified~n", []), unmodified;
+ unmodified;
FileTime >= FieldTime ->
- ?DEBUG("File modified~n", []), modified
+ modified
end
+
end
end.
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index e5780b2a4c..41b2ab950f 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -66,6 +66,7 @@
httpd_file,
httpd_instance_sup,
httpd_log,
+ httpd_logger,
httpd_manager,
httpd_misc_sup,
httpd_request,
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index bf926ec9c1..1d80d604b7 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -79,6 +79,7 @@ all() ->
{group, http_post},
{group, http_rel_path_script_alias},
{group, http_not_sup},
+ {group, https_alert},
{group, https_not_sup},
mime_types_format,
erl_script_timeout_default,
@@ -113,6 +114,7 @@ groups() ->
{http_post, [], [{group, post}]},
{http_not_sup, [], [{group, not_sup}]},
{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]},
{custom, [], [customize, add_default]},
@@ -185,6 +187,9 @@ init_per_suite(Config) ->
setup_tmp_dir(PrivDir),
setup_server_dirs(ServerRoot, DocRoot, DataDir),
{ok, Hostname0} = inet:gethostname(),
+ logger:add_handler_filter(default, inets_httpd, {fun logger_filters:domain/2,
+ {log, equal,[otp,inets, httpd, httpd_test, error]}}),
+ %%logger:set_handler_config(default, formatter, {logger_formatter, #{}}),
Inet =
case (catch ct:get_config(ipv6_hosts)) of
undefined ->
@@ -219,7 +224,8 @@ init_per_group(Group, Config0) when Group == https_basic;
Group == https_auth_api_mnesia;
Group == https_security;
Group == https_reload;
- Group == https_not_sup
+ Group == https_not_sup;
+ Group == https_alert
->
catch crypto:stop(),
try crypto:start() of
@@ -1921,6 +1927,10 @@ erl_script_timeout_apache(Config) when is_list(Config) ->
verify_body(Body, 6000),
inets:stop().
+tls_alert(Config) when is_list(Config) ->
+ SSLOpts = proplists:get_value(client_alert_conf, Config),
+ Port = proplists:get_value(port, Config),
+ {error, {tls_alert, _}} = ssl:connect("localhost", Port, [{verify, verify_peer} | SSLOpts]).
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------
@@ -2054,7 +2064,8 @@ start_apps(Group) when Group == https_basic;
Group == https_htaccess;
Group == https_security;
Group == https_reload;
- Group == https_not_sup
+ Group == https_not_sup;
+ Group == https_alert
->
inets_test_lib:start_apps([inets, asn1, crypto, public_key, ssl]);
start_apps(Group) when Group == http_basic;
@@ -2084,7 +2095,7 @@ server_start(_, HttpdConfig) ->
init_ssl(Group, Config) ->
ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client"]),
ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server"]),
- GenCertData =
+ GenCertData = #{client_config := CConf} =
public_key:pkix_test_data(#{server_chain =>
#{root => [{key, inets_test_lib:hardcode_rsa_key(1)}],
intermediates => [[{key, inets_test_lib:hardcode_rsa_key(2)}]],
@@ -2094,11 +2105,12 @@ init_ssl(Group, Config) ->
#{root => [{key, inets_test_lib:hardcode_rsa_key(4)}],
intermediates => [[{key, inets_test_lib:hardcode_rsa_key(5)}]],
peer => [{key, inets_test_lib:hardcode_rsa_key(6)}]}}),
-
+ [_ | CAs] = proplists:get_value(cacerts, CConf),
+ AlertConf = [{cacerts, CAs} | proplists:delete(cacerts, CConf)],
Conf = inets_test_lib:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
case start_apps(Group) of
ok ->
- init_httpd(Group, [{type, ssl}, {ssl_conf, Conf} | Config]);
+ init_httpd(Group, [{client_alert_conf, AlertConf}, {type, ssl}, {ssl_conf, Conf} | Config]);
_ ->
{skip, "Could not start https apps"}
end.
@@ -2170,7 +2182,8 @@ server_config(http_mime_types, Config0) ->
ServerRoot = proplists:get_value(server_root, Config0),
MimeTypesFile = filename:join([ServerRoot,"config", "mime.types"]),
[{mime_types, MimeTypesFile} | proplists:delete(mime_types, Config1)];
-
+server_config(https_alert, Config) ->
+ basic_conf() ++ server_config(https, Config);
server_config(http, Config) ->
ServerRoot = proplists:get_value(server_root, Config),
[{port, 0},
@@ -2259,7 +2272,9 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
- mod_trace, mod_esi, ?MODULE, mod_cgi, mod_get, mod_head]}].
+ mod_trace, mod_esi, ?MODULE, mod_cgi, mod_get, mod_head]},
+ {logger, [{error, httpd_test}]}].
+
do(ModData) ->
case whereis(propagate_test) of
undefined ->
@@ -2269,9 +2284,9 @@ do(ModData) ->
propagate_test ! {status, Status}
end,
{proceed, ModData#mod.data}.
-
+
not_sup_conf() ->
- [{modules, [mod_get]}].
+ [{modules, [mod_get]}].
auth_access_conf() ->
[{modules, [mod_alias, mod_htaccess, mod_dir, mod_get, mod_head]},