mod_http_upload: Add "custom_headers" option
The new "custom_headers" option allows admins to specify header fields that are added to HTTP responses.
This commit is contained in:
parent
10092e3bd5
commit
9eb68b4ef3
|
@ -146,6 +146,15 @@ The configurable mod_http_upload options are:
|
||||||
In any other case, a 'service-unavailable' error stanza is sent to the
|
In any other case, a 'service-unavailable' error stanza is sent to the
|
||||||
client.
|
client.
|
||||||
|
|
||||||
|
- custom_headers (default: [])
|
||||||
|
|
||||||
|
This option specifies additional header fields to be included in all HTTP
|
||||||
|
responses. For example:
|
||||||
|
|
||||||
|
custom_headers:
|
||||||
|
"Access-Control-Allow-Origin": "*"
|
||||||
|
"Access-Control-Allow-Methods": "GET, PUT"
|
||||||
|
|
||||||
- rm_on_unregister (default: 'true')
|
- rm_on_unregister (default: 'true')
|
||||||
|
|
||||||
This option specifies whether files uploaded by a user should be removed
|
This option specifies whether files uploaded by a user should be removed
|
||||||
|
|
|
@ -185,11 +185,18 @@ mod_opt_type(service_url) ->
|
||||||
fun(<<"http://", _/binary>> = URL) -> URL;
|
fun(<<"http://", _/binary>> = URL) -> URL;
|
||||||
(<<"https://", _/binary>> = URL) -> URL
|
(<<"https://", _/binary>> = URL) -> URL
|
||||||
end;
|
end;
|
||||||
|
mod_opt_type(custom_headers) ->
|
||||||
|
fun(Headers) ->
|
||||||
|
lists:map(fun({K, V}) ->
|
||||||
|
{iolist_to_binary(K), iolist_to_binary(V)}
|
||||||
|
end, Headers)
|
||||||
|
end;
|
||||||
mod_opt_type(rm_on_unregister) ->
|
mod_opt_type(rm_on_unregister) ->
|
||||||
fun(B) when is_boolean(B) -> B end;
|
fun(B) when is_boolean(B) -> B end;
|
||||||
mod_opt_type(_) ->
|
mod_opt_type(_) ->
|
||||||
[host, name, access, max_size, secret_length, jid_in_url, file_mode,
|
[host, name, access, max_size, secret_length, jid_in_url, file_mode,
|
||||||
dir_mode, docroot, put_url, get_url, service_url, rm_on_unregister].
|
dir_mode, docroot, put_url, get_url, service_url, custom_headers,
|
||||||
|
rm_on_unregister].
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% gen_server callbacks.
|
%% gen_server callbacks.
|
||||||
|
@ -347,24 +354,24 @@ process(LocalPath, #request{method = 'PUT', host = Host, ip = IP,
|
||||||
[?ADDR_TO_STR(IP), Host, Path]),
|
[?ADDR_TO_STR(IP), Host, Path]),
|
||||||
case store_file(Path, Data, FileMode, DirMode) of
|
case store_file(Path, Data, FileMode, DirMode) of
|
||||||
ok ->
|
ok ->
|
||||||
http_response(201);
|
http_response(Host, 201);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~s",
|
?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~s",
|
||||||
[Path, ?ADDR_TO_STR(IP), Host, Error]),
|
[Path, ?ADDR_TO_STR(IP), Host, Error]),
|
||||||
http_response(500)
|
http_response(Host, 500)
|
||||||
end;
|
end;
|
||||||
{ok, Size, Path} ->
|
{ok, Size, Path} ->
|
||||||
?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B",
|
?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B",
|
||||||
[Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]),
|
[Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]),
|
||||||
http_response(413);
|
http_response(Host, 413);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
?INFO_MSG("Rejecting file from ~s for ~s: ~p",
|
?INFO_MSG("Rejecting file from ~s for ~s: ~p",
|
||||||
[?ADDR_TO_STR(IP), Host, Error]),
|
[?ADDR_TO_STR(IP), Host, Error]),
|
||||||
http_response(403);
|
http_response(Host, 403);
|
||||||
Error ->
|
Error ->
|
||||||
?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p",
|
?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p",
|
||||||
[?ADDR_TO_STR(IP), Host, Error]),
|
[?ADDR_TO_STR(IP), Host, Error]),
|
||||||
http_response(500)
|
http_response(Host, 500)
|
||||||
end;
|
end;
|
||||||
process(LocalPath, #request{method = 'GET', host = Host, ip = IP}) ->
|
process(LocalPath, #request{method = 'GET', host = Host, ip = IP}) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
|
@ -385,33 +392,33 @@ process(LocalPath, #request{method = 'GET', host = Host, ip = IP}) ->
|
||||||
$", FileName/binary, $">>}]
|
$", FileName/binary, $">>}]
|
||||||
end,
|
end,
|
||||||
Headers2 = [{<<"Content-Type">>, ContentType} | Headers1],
|
Headers2 = [{<<"Content-Type">>, ContentType} | Headers1],
|
||||||
http_response(200, Headers2, Data);
|
http_response(Host, 200, Headers2, Data);
|
||||||
{error, eacces} ->
|
{error, eacces} ->
|
||||||
?INFO_MSG("Cannot serve ~s to ~s: Permission denied",
|
?INFO_MSG("Cannot serve ~s to ~s: Permission denied",
|
||||||
[Path, ?ADDR_TO_STR(IP)]),
|
[Path, ?ADDR_TO_STR(IP)]),
|
||||||
http_response(403);
|
http_response(Host, 403);
|
||||||
{error, enoent} ->
|
{error, enoent} ->
|
||||||
?INFO_MSG("Cannot serve ~s to ~s: No such file or directory",
|
?INFO_MSG("Cannot serve ~s to ~s: No such file or directory",
|
||||||
[Path, ?ADDR_TO_STR(IP)]),
|
[Path, ?ADDR_TO_STR(IP)]),
|
||||||
http_response(404);
|
http_response(Host, 404);
|
||||||
{error, eisdir} ->
|
{error, eisdir} ->
|
||||||
?INFO_MSG("Cannot serve ~s to ~s: Is a directory",
|
?INFO_MSG("Cannot serve ~s to ~s: Is a directory",
|
||||||
[Path, ?ADDR_TO_STR(IP)]),
|
[Path, ?ADDR_TO_STR(IP)]),
|
||||||
http_response(404);
|
http_response(Host, 404);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
?INFO_MSG("Cannot serve ~s to ~s: ~p",
|
?INFO_MSG("Cannot serve ~s to ~s: ~p",
|
||||||
[Path, ?ADDR_TO_STR(IP), Error]),
|
[Path, ?ADDR_TO_STR(IP), Error]),
|
||||||
http_response(500)
|
http_response(Host, 500)
|
||||||
end;
|
end;
|
||||||
Error ->
|
Error ->
|
||||||
?ERROR_MSG("Cannot handle GET request from ~s for ~s: ~p",
|
?ERROR_MSG("Cannot handle GET request from ~s for ~s: ~p",
|
||||||
[?ADDR_TO_STR(IP), Host, Error]),
|
[?ADDR_TO_STR(IP), Host, Error]),
|
||||||
http_response(500)
|
http_response(Host, 500)
|
||||||
end;
|
end;
|
||||||
process(_LocalPath, #request{method = Method, host = Host, ip = IP}) ->
|
process(_LocalPath, #request{method = Method, host = Host, ip = IP}) ->
|
||||||
?DEBUG("Rejecting ~s request from ~s for ~s",
|
?DEBUG("Rejecting ~s request from ~s for ~s",
|
||||||
[Method, ?ADDR_TO_STR(IP), Host]),
|
[Method, ?ADDR_TO_STR(IP), Host]),
|
||||||
http_response(405, [{<<"Allow">>, <<"GET, PUT">>}]).
|
http_response(Host, 405, [{<<"Allow">>, <<"GET, PUT">>}]).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Internal functions.
|
%% Internal functions.
|
||||||
|
@ -689,30 +696,40 @@ guess_content_type(FileName) ->
|
||||||
?DEFAULT_CONTENT_TYPE,
|
?DEFAULT_CONTENT_TYPE,
|
||||||
?CONTENT_TYPES).
|
?CONTENT_TYPES).
|
||||||
|
|
||||||
-spec http_response(100..599)
|
-spec http_response(binary(), 100..599)
|
||||||
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
||||||
|
|
||||||
http_response(Code) ->
|
http_response(Host, Code) ->
|
||||||
http_response(Code, []).
|
http_response(Host, Code, []).
|
||||||
|
|
||||||
-spec http_response(100..599, [{binary(), binary()}])
|
-spec http_response(binary(), 100..599, [{binary(), binary()}])
|
||||||
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
||||||
|
|
||||||
http_response(Code, ExtraHeaders) ->
|
http_response(Host, Code, ExtraHeaders) ->
|
||||||
http_response(Code, ExtraHeaders, <<(code_to_message(Code))/binary, $\n>>).
|
Message = <<(code_to_message(Code))/binary, $\n>>,
|
||||||
|
http_response(Host, Code, ExtraHeaders, Message).
|
||||||
|
|
||||||
-spec http_response(100..599, [{binary(), binary()}], binary())
|
-spec http_response(binary(), 100..599, [{binary(), binary()}], binary())
|
||||||
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
-> {pos_integer(), [{binary(), binary()}], binary()}.
|
||||||
|
|
||||||
http_response(Code, ExtraHeaders, Body) ->
|
http_response(Host, Code, ExtraHeaders, Body) ->
|
||||||
ServerHeader = {<<"Server">>, <<"ejabberd ", (?VERSION)/binary>>},
|
ServerHeader = {<<"Server">>, <<"ejabberd ", (?VERSION)/binary>>},
|
||||||
|
CustomHeaders =
|
||||||
|
gen_mod:get_module_opt(Host, ?MODULE, custom_headers,
|
||||||
|
fun(Headers) ->
|
||||||
|
lists:map(fun({K, V}) ->
|
||||||
|
{iolist_to_binary(K),
|
||||||
|
iolist_to_binary(V)}
|
||||||
|
end, Headers)
|
||||||
|
end,
|
||||||
|
[]),
|
||||||
Headers = case proplists:is_defined(<<"Content-Type">>, ExtraHeaders) of
|
Headers = case proplists:is_defined(<<"Content-Type">>, ExtraHeaders) of
|
||||||
true ->
|
true ->
|
||||||
[ServerHeader | ExtraHeaders];
|
[ServerHeader | ExtraHeaders];
|
||||||
false ->
|
false ->
|
||||||
[ServerHeader, {<<"Content-Type">>, <<"text/plain">>} |
|
[ServerHeader, {<<"Content-Type">>, <<"text/plain">>} |
|
||||||
ExtraHeaders]
|
ExtraHeaders]
|
||||||
end,
|
end ++ CustomHeaders,
|
||||||
{Code, Headers, Body}.
|
{Code, Headers, Body}.
|
||||||
|
|
||||||
-spec code_to_message(100..599) -> binary().
|
-spec code_to_message(100..599) -> binary().
|
||||||
|
|
Loading…
Reference in New Issue