25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Added accesslog parameter to record requests log in a file similar to Apache (thanks to Jerome Sautret)

SVN Revision: 2184
This commit is contained in:
Badlop 2009-06-16 13:52:12 +00:00
parent 487b80b9b0
commit b57248e822

View File

@ -15,14 +15,16 @@
-behaviour(gen_mod). -behaviour(gen_mod).
-export([ -export([
start/2, start/2,
stop/1, stop/1,
process/2 process/2,
ctl_process/2
]). ]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
-include("ejabberd_http.hrl"). -include("ejabberd_http.hrl").
-include("ejabberd_ctl.hrl").
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% REQUEST HANDLERS %%% REQUEST HANDLERS
@ -30,7 +32,7 @@
%%----------------------------------------------------------------------- %%-----------------------------------------------------------------------
%% FUNCTION %% FUNCTION
%% %%
%% process/2 %% process/2
%% %%
%% PURPOSE %% PURPOSE
@ -48,8 +50,21 @@
%% %%
%%----------------------------------------------------------------------- %%-----------------------------------------------------------------------
process(LocalPath, _Request) ->
process(LocalPath, Request) ->
?DEBUG("Requested ~p", [LocalPath]), ?DEBUG("Requested ~p", [LocalPath]),
Result = serve(LocalPath),
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
{Code, _, _} = Result,
log(AccessFile, Code, Request)
end,
Result.
serve(LocalPath) ->
[{docroot, DocRoot}] = ets:lookup(mod_http_fileserver, docroot), [{docroot, DocRoot}] = ets:lookup(mod_http_fileserver, docroot),
FileName = filename:join(filename:split(DocRoot) ++ LocalPath), FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
case file:read_file(FileName) of case file:read_file(FileName) of
@ -68,11 +83,40 @@ process(LocalPath, _Request) ->
end end
end. end.
ctl_process(_Val, ["reopen-weblog"]) ->
mod_http_fileserver_server ! reopenlog,
?STATUS_SUCCESS;
ctl_process(Val, _Args) ->
Val.
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% UTILITIES %%% UTILITIES
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
join([], _) ->
"";
join([E], _) ->
E;
join([H | T], Separator) ->
lists:foldl(fun(E, Acc) -> lists:concat([Acc, Separator, E]) end, H, T).
log(File, Code, Request) ->
{{Year, Month, Day}, {Hour, Minute, Second}} = calendar:local_time(),
IP = join(tuple_to_list(Request#request.ip), "."),
Path = join(Request#request.path, "/"),
Query = case join(lists:map(fun(E) -> lists:concat([element(1, E), "=", element(2, E)]) end,
Request#request.q), "&") of
[] ->
"";
String ->
[$? | String]
end,
% combined apache like log format :
% 127.0.0.1 - - [28/Mar/2007:18:41:55 +0200] "GET / HTTP/1.1" 302 303 "-" "tsung"
% XXX TODO some fields are harcoded/missing (reply size, user agent or referer for example)
io:format(File, "~p - - [~p/~p/~p:~p:~p:~p] \"~s /~s~s\" ~p -1 \"-\" \"-\"~n",
[IP, Day, Month, Year, Hour, Minute, Second, Request#request.method, Path, Query, Code]).
content_type(Filename) -> content_type(Filename) ->
case httpd_util:to_lower(filename:extension(Filename)) of case httpd_util:to_lower(filename:extension(Filename)) of
".jpg" -> "image/jpeg"; ".jpg" -> "image/jpeg";
@ -88,25 +132,78 @@ content_type(Filename) ->
_Else -> "application/octet-stream" _Else -> "application/octet-stream"
end. end.
open_file(Filename) ->
case file:open(Filename, [append]) of
{ok, File} ->
ets:insert(mod_http_fileserver, {accessfile, File}),
ok;
{error, _Reason} ->
{'EXIT', {unaccessible_accessfile, ?MODULE}}
end.
loop(Filename) ->
receive
reopenlog ->
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
file:close(AccessFile),
case open_file(Filename) of
ok ->
ok;
_ ->
error
end
end,
loop(Filename);
stop ->
ok
end.
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
%%% BEHAVIOUR CALLBACKS %%% BEHAVIOUR CALLBACKS
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
start(_Host, Opts) -> start(_Host, Opts) ->
ejabberd_ctl:register_commands([{"reopen-weblog", "reopen http fileserver log file"}],
?MODULE, ctl_process),
case gen_mod:get_opt(docroot, Opts, undefined) of case gen_mod:get_opt(docroot, Opts, undefined) of
undefined -> undefined ->
{'EXIT', {missing_document_root, ?MODULE}}; {'EXIT', {missing_document_root, ?MODULE}};
DocRoot -> DocRoot ->
case filelib:is_dir(DocRoot) of case filelib:is_dir(DocRoot) of
true -> true ->
ets:new(mod_http_fileserver, [named_table, bag]), % XXX WARNING, using a single ets table name will
% not work with virtual hosts
ets:new(mod_http_fileserver, [named_table, public]),
ets:insert(mod_http_fileserver, [{docroot, DocRoot}]), ets:insert(mod_http_fileserver, [{docroot, DocRoot}]),
ok; case gen_mod:get_opt(accesslog, Opts, undefined) of
undefined ->
ok;
Filename ->
% XXX same remark as above for proc name
register(mod_http_fileserver_server, spawn(?MODULE, loop, [Filename])),
open_file(Filename)
end;
_Else -> _Else ->
{'EXIT', {unaccessible_document_root, ?MODULE}} {'EXIT', {unaccessible_document_root, ?MODULE}}
end end
end. end.
stop(_Host) -> stop(_Host) ->
ok. case ets:info(mod_http_fileserver, name) of
undefined ->
ok;
_ ->
case ets:lookup(mod_http_fileserver, accessfile) of
undefined ->
ok;
[{accessfile, AccessFile}] ->
mod_http_fileserver_server ! stop,
file:close(AccessFile)
end,
ets:delete(mod_http_fileserver)
end,
ok.