diff options
author | Erlang/OTP <otp@erlang.org> | 2019-10-16 09:01:04 +0200 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2019-10-16 09:01:04 +0200 |
commit | 0010f52aef611fa6c2604504ebb278f4f7676710 (patch) | |
tree | bc0261cf64e53c2f2bd765033f3a69ed333f0910 /lib/inets | |
parent | d233c924fe2de37c60b8d35898e57a8dcf6924d8 (diff) | |
parent | 6b5f1ff4c6afab8b4dac36ea129e84ab9524c084 (diff) | |
download | erlang-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')
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]}, |