fix(s3): handle extra configured headers correctly

* Header names in config become atoms.
  (Probably because of blanket `unsafe_atom_key_map/1` in `emqx_config`)
* Header names should be normalized to lowercase.
  (Otherwise signature will be incorrect)
This commit is contained in:
Andrew Mayorov 2023-12-28 10:20:22 +01:00
parent d26f56e99b
commit 33ef964582
No known key found for this signature in database
GPG Key ID: 2837C62ACFBFED5D
2 changed files with 35 additions and 12 deletions

View File

@ -388,7 +388,7 @@ with_path_and_query_only(Url, Fun) ->
%% Users provide headers as a map, but erlcloud expects a list of tuples with string keys and values.
headers_user_to_erlcloud_request(UserHeaders) ->
[{to_list_string(K), V} || {K, V} <- maps:to_list(UserHeaders)].
[{string:to_lower(to_list_string(K)), V} || {K, V} <- maps:to_list(UserHeaders)].
%% Ehttpc returns operates on headers as a list of tuples with binary keys.
%% Erlcloud expects a list of tuples with string values and lowcase string keys
@ -409,6 +409,8 @@ to_binary(Val) when is_binary(Val) -> Val.
to_list_string(Val) when is_binary(Val) ->
binary_to_list(Val);
to_list_string(Val) when is_atom(Val) ->
atom_to_list(Val);
to_list_string(Val) when is_list(Val) ->
Val.

View File

@ -142,6 +142,22 @@ t_no_acl(Config) ->
ok = emqx_s3_client:put_object(Client, Key, <<"data">>).
t_extra_headers(Config0) ->
Config = [{extra_headers, #{'Content-Type' => <<"application/json">>}} | Config0],
Key = ?config(key, Config),
Client = client(Config),
Data = #{foo => bar},
ok = emqx_s3_client:put_object(Client, Key, emqx_utils_json:encode(Data)),
Url = emqx_s3_client:uri(Client, Key),
{ok, {{_StatusLine, 200, "OK"}, _Headers, Content}} = httpc:request(Url),
?_assertEqual(
Data,
emqx_utils_json:decode(Content)
).
%%--------------------------------------------------------------------
%% Helpers
%%--------------------------------------------------------------------
@ -154,17 +170,22 @@ client(Config) ->
profile_config(Config) ->
ProfileConfig0 = emqx_s3_test_helpers:base_config(?config(conn_type, Config)),
ProfileConfig1 = maps:put(
bucket,
?config(bucket, Config),
ProfileConfig0
),
ProfileConfig2 = emqx_utils_maps:deep_put(
[transport_options, pool_type],
ProfileConfig1,
?config(pool_type, Config)
),
ProfileConfig2.
maps:fold(
fun inject_config/3,
ProfileConfig0,
#{
bucket => ?config(bucket, Config),
[transport_options, pool_type] => ?config(pool_type, Config),
[transport_options, headers] => ?config(extra_headers, Config)
}
).
inject_config(_Key, undefined, ProfileConfig) ->
ProfileConfig;
inject_config(KeyPath, Value, ProfileConfig) when is_list(KeyPath) ->
emqx_utils_maps:deep_put(KeyPath, ProfileConfig, Value);
inject_config(Key, Value, ProfileConfig) ->
maps:put(Key, Value, ProfileConfig).
data(Size) ->
iolist_to_binary([$a || _ <- lists:seq(1, Size)]).