From 41de5e78d0f792586487e33a8b1e2a0cf405e0be Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 27 Mar 2017 23:19:11 +0200 Subject: [PATCH 1/3] ejabberd_http: Add "custom_headers" option If the new listener option "custom_headers" is specified, include those headers with the HTTP(S) response. Closes #517. --- src/ejabberd_http.erl | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4b1242568..4c5dd8ebe 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -68,6 +68,7 @@ end_of_request = false, options = [], default_host, + custom_headers, trail = <<>>, addr_re }). @@ -167,10 +168,15 @@ init({SockMod, Socket}, Opts) -> DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined), {ok, RE} = re:compile(<<"^(?:\\[(.*?)\\]|(.*?))(?::(\\d+))?$">>), + CustomHeaders = gen_mod:get_opt(custom_headers, Opts, + fun(L) when is_list(L) -> L end, + []), + ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), State = #state{sockmod = SockMod1, socket = Socket1, default_host = DefaultHost, + custom_headers = CustomHeaders, options = Opts, request_handlers = RequestHandlers, addr_re = RE}, @@ -309,6 +315,7 @@ process_header(State, Data) -> trail = State3#state.trail, options = State#state.options, default_host = State#state.default_host, + custom_headers = State#state.custom_headers, request_handlers = State#state.request_handlers, addr_re = State#state.addr_re}; _ -> @@ -316,6 +323,7 @@ process_header(State, Data) -> trail = State3#state.trail, options = State#state.options, default_host = State#state.default_host, + custom_headers = State#state.custom_headers, request_handlers = State#state.request_handlers, addr_re = State#state.addr_re} end; @@ -323,6 +331,7 @@ process_header(State, Data) -> #state{end_of_request = true, options = State#state.options, default_host = State#state.default_host, + custom_headers = State#state.custom_headers, request_handlers = State#state.request_handlers, addr_re = State#state.addr_re} end. @@ -446,6 +455,7 @@ process_request(#state{request_method = Method, request_tp = TP, request_headers = RequestHeaders, request_handlers = RequestHandlers, + custom_headers = CustomHeaders, trail = Trail} = State) -> case extract_path_query(State) of {State2, false} -> @@ -478,18 +488,21 @@ process_request(#state{request_method = Method, ip = IP}, Res = case process(RequestHandlers, Request, Socket, SockMod, Trail) of El when is_record(El, xmlel) -> - make_xhtml_output(State, 200, [], El); + make_xhtml_output(State, 200, CustomHeaders, El); {Status, Headers, El} when is_record(El, xmlel) -> - make_xhtml_output(State, Status, Headers, El); + make_xhtml_output(State, Status, + Headers ++ CustomHeaders, El); Output when is_binary(Output) or is_list(Output) -> - make_text_output(State, 200, [], Output); + make_text_output(State, 200, CustomHeaders, Output); {Status, Headers, Output} when is_binary(Output) or is_list(Output) -> - make_text_output(State, Status, Headers, Output); + make_text_output(State, Status, + Headers ++ CustomHeaders, Output); {Status, Reason, Headers, Output} when is_binary(Output) or is_list(Output) -> - make_text_output(State, Status, Reason, Headers, Output); + make_text_output(State, Status, Reason, + Headers ++ CustomHeaders, Output); _ -> none end, @@ -497,7 +510,7 @@ process_request(#state{request_method = Method, end. make_bad_request(State) -> - make_xhtml_output(State, 400, [], + make_xhtml_output(State, 400, State#state.custom_headers, ejabberd_web:make_xhtml([#xmlel{name = <<"h1">>, attrs = [], children = From 191fc1b4e87665df769ddac22335ac246b8d6f63 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 27 Mar 2017 23:52:49 +0200 Subject: [PATCH 2/3] ejabberd_http: Expand @VERSION@ in custom headers Let ejabberd_http expand the @VERSION@ keyword to the ejabberd version if specified in the "custom_headers" listener option. Closes #1414. --- src/ejabberd_http.erl | 7 ++++++- src/jlib.erl | 8 +++++++- src/mod_http_upload.erl | 10 ++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4c5dd8ebe..c3f962fbc 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -169,7 +169,7 @@ init({SockMod, Socket}, Opts) -> {ok, RE} = re:compile(<<"^(?:\\[(.*?)\\]|(.*?))(?::(\\d+))?$">>), CustomHeaders = gen_mod:get_opt(custom_headers, Opts, - fun(L) when is_list(L) -> L end, + fun expand_custom_headers/1, []), ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), @@ -733,6 +733,11 @@ rest_dir(0, Path, <>) -> rest_dir(0, <>, T); rest_dir(N, Path, <<_H, T/binary>>) -> rest_dir(N, Path, T). +expand_custom_headers(Headers) -> + lists:map(fun({K, V}) -> + {K, jlib:expand_keyword(<<"@VERSION@">>, V, ?VERSION)} + end, Headers). + %% hex_to_integer hex_to_integer(Hex) -> diff --git a/src/jlib.erl b/src/jlib.erl index 12bedbc7e..3b6a6556a 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -37,7 +37,7 @@ -export([tolower/1, term_to_base64/1, base64_to_term/1, decode_base64/1, encode_base64/1, ip_to_list/1, - hex_to_bin/1, hex_to_base64/1, + hex_to_bin/1, hex_to_base64/1, expand_keyword/3, atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, expr_to_term/1, term_to_expr/1]). @@ -934,6 +934,12 @@ hex_to_bin([H1, H2 | T], Acc) -> hex_to_base64(Hex) -> encode_base64(hex_to_bin(Hex)). +-spec expand_keyword(binary(), binary(), binary()) -> binary(). + +expand_keyword(Keyword, Input, Replacement) -> + Parts = binary:split(Input, Keyword, [global]), + str:join(Parts, Replacement). + binary_to_atom(Bin) -> erlang:binary_to_atom(Bin, utf8). diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 59570b0b5..31494c2e1 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -500,16 +500,14 @@ get_proc_name(ServerHost, ModuleName) -> -spec expand_home(binary()) -> binary(). -expand_home(Subject) -> +expand_home(Input) -> {ok, [[Home]]} = init:get_argument(home), - Parts = binary:split(Subject, <<"@HOME@">>, [global]), - str:join(Parts, list_to_binary(Home)). + jlib:expand_keyword(<<"@HOME@">>, Input, Home). -spec expand_host(binary(), binary()) -> binary(). -expand_host(Subject, Host) -> - Parts = binary:split(Subject, <<"@HOST@">>, [global]), - str:join(Parts, Host). +expand_host(Input, Host) -> + jlib:expand_keyword(<<"@HOST@">>, Input, Host). %%-------------------------------------------------------------------- %% Internal functions. From 510fde58d8aee68f5b81064209765ac4259017ac Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 28 Mar 2017 00:03:17 +0200 Subject: [PATCH 3/3] mod_http_upload: Don't add "Server" header line Administrators can add the "Server" header line using the new listener option "custom_headers", if desired. --- src/mod_http_upload.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 31494c2e1..cb62bec7e 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -833,7 +833,6 @@ http_response(Host, Code, ExtraHeaders) -> -> {pos_integer(), [{binary(), binary()}], binary()}. http_response(Host, Code, ExtraHeaders, Body) -> - ServerHeader = {<<"Server">>, <<"ejabberd ", (?VERSION)/binary>>}, CustomHeaders = gen_mod:get_module_opt(Host, ?MODULE, custom_headers, fun(Headers) -> @@ -845,10 +844,9 @@ http_response(Host, Code, ExtraHeaders, Body) -> []), Headers = case proplists:is_defined(<<"Content-Type">>, ExtraHeaders) of true -> - [ServerHeader | ExtraHeaders]; + ExtraHeaders; false -> - [ServerHeader, {<<"Content-Type">>, <<"text/plain">>} | - ExtraHeaders] + [{<<"Content-Type">>, <<"text/plain">>} | ExtraHeaders] end ++ CustomHeaders, {Code, Headers, Body}.