diff --git a/doc/guide.html b/doc/guide.html
index 3ff220a13..8f1a32473 100644
--- a/doc/guide.html
+++ b/doc/guide.html
@@ -2143,6 +2143,9 @@ Directory to serve the files.
{accesslog, Path}
File to log accesses using an Apache-like format.
No log will be recorded if this option is not specified.
+{custom_headers, [ {Name, Value}, ...]}
+Indicate custom HTTP headers to be included in all responses.
+Default value is: []
{directory_indices, [Index, ...]}
Indicate one or more directory index files, similarly to Apache’s
DirectoryIndex variable. When a web request hits a directory
@@ -2172,6 +2175,9 @@ To use this module you must enable it:
{".png", "image/png"},
{".jpg", undefined}
]},
+ {custom_headers, [{"X-Powered-By", "Erlang/OTP"},
+ {"X-Fry", "It's a widely-believed fact!"}
+ ]},
{default_content_type, "text/html"}
]
},
diff --git a/doc/guide.tex b/doc/guide.tex
index df8fc97a1..95fc54fe1 100644
--- a/doc/guide.tex
+++ b/doc/guide.tex
@@ -2832,6 +2832,9 @@ Options:
\titem{\{accesslog, Path\}} \ind{options!accesslog}
File to log accesses using an Apache-like format.
No log will be recorded if this option is not specified.
+ \titem{\{custom\_headers, [ \{Name, Value\}, ...]\}} \ind{options!customheaders}
+ Indicate custom HTTP headers to be included in all responses.
+ Default value is: \term{[]}
\titem{\{directory\_indices, [Index, ...]\}} \ind{options!directoryindices}
Indicate one or more directory index files, similarly to Apache's
DirectoryIndex variable. When a web request hits a directory
@@ -2869,6 +2872,9 @@ To use this module you must enable it:
{".png", "image/png"},
{".jpg", undefined}
]},
+ {custom_headers, [{"X-Powered-By", "Erlang/OTP"},
+ {"X-Fry", "It's a widely-believed fact!"}
+ ]},
{default_content_type, "text/html"}
]
},
diff --git a/src/web/mod_http_fileserver.erl b/src/web/mod_http_fileserver.erl
index a5a021c00..09472ce17 100644
--- a/src/web/mod_http_fileserver.erl
+++ b/src/web/mod_http_fileserver.erl
@@ -67,7 +67,7 @@
}).
-record(state, {host, docroot, accesslog, accesslogfd, directory_indices,
- default_content_type, content_types = []}).
+ custom_headers, default_content_type, content_types = []}).
-define(PROCNAME, ejabberd_mod_http_fileserver).
@@ -135,12 +135,13 @@ start_link(Host, Opts) ->
init([Host, Opts]) ->
try initialize(Host, Opts) of
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- DefaultContentType, ContentTypes} ->
+ CustomHeaders, DefaultContentType, ContentTypes} ->
{ok, #state{host = Host,
accesslog = AccessLog,
accesslogfd = AccessLogFD,
docroot = DocRoot,
directory_indices = DirectoryIndices,
+ custom_headers = CustomHeaders,
default_content_type = DefaultContentType,
content_types = ContentTypes}}
catch
@@ -157,12 +158,13 @@ initialize(Host, Opts) ->
AccessLog = gen_mod:get_opt(accesslog, Opts, undefined),
AccessLogFD = try_open_log(AccessLog, Host),
DirectoryIndices = gen_mod:get_opt(directory_indices, Opts, []),
+ CustomHeaders = gen_mod:get_opt(custom_headers, Opts, []),
DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
?DEFAULT_CONTENT_TYPE),
ContentTypes = build_list_content_types(gen_mod:get_opt(content_types, Opts, []), ?DEFAULT_CONTENT_TYPES),
?INFO_MSG("initialize: ~n ~p", [ContentTypes]),%+++
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
- DefaultContentType, ContentTypes}.
+ CustomHeaders, DefaultContentType, ContentTypes}.
%% @spec (AdminCTs::[CT], Default::[CT]) -> [CT]
%% where CT = {Extension::string(), Value}
@@ -226,6 +228,7 @@ try_open_log(FN, Host) ->
%%--------------------------------------------------------------------
handle_call({serve, LocalPath}, _From, State) ->
Reply = serve(LocalPath, State#state.docroot, State#state.directory_indices,
+ State#state.custom_headers,
State#state.default_content_type, State#state.content_types),
{reply, Reply, State};
handle_call(_Request, _From, State) ->
@@ -293,42 +296,44 @@ process(LocalPath, Request) ->
ejabberd_web:error(not_found)
end.
-serve(LocalPath, DocRoot, DirectoryIndices, DefaultContentType, ContentTypes) ->
+serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes) ->
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
case file:read_file_info(FileName) of
{error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
{error, eacces} -> ?HTTP_ERR_FORBIDDEN;
{ok, #file_info{type = directory}} -> serve_index(FileName,
DirectoryIndices,
+ CustomHeaders,
DefaultContentType,
ContentTypes);
{ok, FileInfo} -> serve_file(FileInfo, FileName,
+ CustomHeaders,
DefaultContentType,
ContentTypes)
end.
%% Troll through the directory indices attempting to find one which
%% works, if none can be found, return a 404.
-serve_index(_FileName, [], _DefaultContentType, _ContentTypes) ->
+serve_index(_FileName, [], CH, _DefaultContentType, _ContentTypes) ->
?HTTP_ERR_FILE_NOT_FOUND;
-serve_index(FileName, [Index | T], DefaultContentType, ContentTypes) ->
+serve_index(FileName, [Index | T], CH, DefaultContentType, ContentTypes) ->
IndexFileName = filename:join([FileName] ++ [Index]),
case file:read_file_info(IndexFileName) of
- {error, _Error} -> serve_index(FileName, T, DefaultContentType, ContentTypes);
- {ok, #file_info{type = directory}} -> serve_index(FileName, T, DefaultContentType, ContentTypes);
- {ok, FileInfo} -> serve_file(FileInfo, IndexFileName, DefaultContentType, ContentTypes)
+ {error, _Error} -> serve_index(FileName, T, CH, DefaultContentType, ContentTypes);
+ {ok, #file_info{type = directory}} -> serve_index(FileName, T, CH, DefaultContentType, ContentTypes);
+ {ok, FileInfo} -> serve_file(FileInfo, IndexFileName, CH, DefaultContentType, ContentTypes)
end.
%% Assume the file exists if we got this far and attempt to read it in
%% and serve it up.
-serve_file(FileInfo, FileName, DefaultContentType, ContentTypes) ->
+serve_file(FileInfo, FileName, CustomHeaders, DefaultContentType, ContentTypes) ->
?DEBUG("Delivering: ~s", [FileName]),
{ok, FileContents} = file:read_file(FileName),
ContentType = content_type(FileName, DefaultContentType, ContentTypes),
{FileInfo#file_info.size,
200, [{"Server", "ejabberd"},
{"Last-Modified", last_modified(FileInfo)},
- {"Content-Type", ContentType}],
+ {"Content-Type", ContentType} | CustomHeaders],
FileContents}.
%%----------------------------------------------------------------------