From 357e7e117dc32b1de7a30cd8aa411d7220d230fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 21 Feb 2020 12:19:02 +0100 Subject: [PATCH] Make http heades passed in custom_headers override builtin headers Previously we just appended them, so sometimes we just had duplicates This fixes issue #3056 --- src/ejabberd_http.erl | 14 ++++++++++---- src/mod_http_fileserver.erl | 16 +++++++++------- src/mod_http_upload.erl | 6 +++--- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 89c5352fc..fdc9321ef 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -31,7 +31,8 @@ %% External exports -export([start/3, start_link/3, accept/1, receive_headers/1, recv_file/2, - listen_opt_type/1, listen_options/0]). + listen_opt_type/1, listen_options/0, + apply_custom_headers/2]). -export([init/3]). @@ -491,19 +492,19 @@ process_request(#state{request_method = Method, {Status, Headers, El} when is_record(El, xmlel) -> make_xhtml_output(State, Status, - Headers ++ CustomHeaders, El); + apply_custom_headers(Headers, CustomHeaders), El); Output when is_binary(Output) or is_list(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 ++ CustomHeaders, Output); + apply_custom_headers(Headers, CustomHeaders), Output); {Status, Headers, {file, FileName}} -> make_file_output(State, Status, Headers, FileName); {Status, Reason, Headers, Output} when is_binary(Output) or is_list(Output) -> make_text_output(State, Status, Reason, - Headers ++ CustomHeaders, Output); + apply_custom_headers(Headers, CustomHeaders), Output); _ -> none end, @@ -855,6 +856,11 @@ parse_urlencoded(<<>>, Last, Cur, _State) -> [{Last, Cur}]; parse_urlencoded(undefined, _, _, _) -> []. +apply_custom_headers(Headers, CustomHeaders) -> + M = maps:merge(maps:from_list(Headers), + maps:from_list(CustomHeaders)), + maps:to_list(M). + % The following code is mostly taken from yaws_ssl.erl toupper(C) when C >= $a andalso C =< $z -> C - 32; diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 9a8bc3f8f..287fce624 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -345,9 +345,10 @@ serve_index(FileName, [Index | T], CH, DefaultContentType, ContentTypes) -> serve_not_modified(FileInfo, FileName, CustomHeaders) -> ?DEBUG("Delivering not modified: ~ts", [FileName]), {0, 304, - [{<<"Server">>, <<"ejabberd">>}, - {<<"Last-Modified">>, last_modified(FileInfo)} - | CustomHeaders], <<>>}. + ejabberd_http:apply_custom_headers( + [{<<"Server">>, <<"ejabberd">>}, + {<<"Last-Modified">>, last_modified(FileInfo)}], + CustomHeaders), <<>>}. %% Assume the file exists if we got this far and attempt to read it in %% and serve it up. @@ -356,10 +357,11 @@ serve_file(FileInfo, FileName, CustomHeaders, DefaultContentType, ContentTypes) ContentType = content_type(FileName, DefaultContentType, ContentTypes), {FileInfo#file_info.size, 200, - [{<<"Server">>, <<"ejabberd">>}, - {<<"Last-Modified">>, last_modified(FileInfo)}, - {<<"Content-Type">>, ContentType} - | CustomHeaders], + ejabberd_http:apply_custom_headers( + [{<<"Server">>, <<"ejabberd">>}, + {<<"Last-Modified">>, last_modified(FileInfo)}, + {<<"Content-Type">>, ContentType}], + CustomHeaders), {file, FileName}}. %%---------------------------------------------------------------------- diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 689ef4ec2..51d7761ab 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -545,7 +545,7 @@ process(_LocalPath, #request{method = 'PUT', host = Host, ip = IP, ok -> http_response(201, CustomHeaders); {ok, Headers, OutData} -> - http_response(201, Headers ++ CustomHeaders, OutData); + http_response(201, ejabberd_http:apply_custom_headers(Headers, CustomHeaders), OutData); {error, closed} -> ?DEBUG("Cannot store file ~ts from ~ts for ~ts: connection closed", [Path, encode_addr(IP), Host]), @@ -595,7 +595,7 @@ process(_LocalPath, #request{method = Method, host = Host, ip = IP} = Request) $", FileName/binary, $">>}] end, Headers2 = [{<<"Content-Type">>, ContentType} | Headers1], - Headers3 = Headers2 ++ CustomHeaders, + Headers3 = ejabberd_http:apply_custom_headers(Headers2, CustomHeaders), http_response(200, Headers3, {file, Path}); {error, eacces} -> ?WARNING_MSG("Cannot serve ~ts to ~ts: Permission denied", @@ -633,7 +633,7 @@ process(_LocalPath, #request{method = 'OPTIONS', host = Host, try gen_server:call(Proc, get_conf, ?CALL_TIMEOUT) of {ok, _DocRoot, CustomHeaders} -> AllowHeader = {<<"Allow">>, <<"OPTIONS, HEAD, GET, PUT">>}, - http_response(200, [AllowHeader | CustomHeaders]) + http_response(200, ejabberd_http:apply_custom_headers([AllowHeader], CustomHeaders)) catch exit:{noproc, _} -> ?WARNING_MSG("Cannot handle OPTIONS request from ~ts for ~ts: "