Procházet zdrojové kódy

fix: duplicated headers in http data integration.

prior to this fix, if headers are configured for both
http action and connector, headers configured in action will repeat
itself if the same header name is found in connector.
zmstone před 1 rokem
rodič
revize
f7554bc8e1

+ 1 - 1
apps/emqx_bridge_http/src/emqx_bridge_http.app.src

@@ -1,6 +1,6 @@
 {application, emqx_bridge_http, [
 {application, emqx_bridge_http, [
     {description, "EMQX HTTP Bridge and Connector Application"},
     {description, "EMQX HTTP Bridge and Connector Application"},
-    {vsn, "0.3.4"},
+    {vsn, "0.3.5"},
     {registered, []},
     {registered, []},
     {applications, [kernel, stdlib, emqx_resource, ehttpc]},
     {applications, [kernel, stdlib, emqx_resource, ehttpc]},
     {env, [
     {env, [

+ 10 - 18
apps/emqx_bridge_http/src/emqx_bridge_http_connector.erl

@@ -753,11 +753,11 @@ process_request_and_action(Request, ActionState, Msg) ->
             _ -> join_paths(PathPrefix, PathSuffix)
             _ -> join_paths(PathPrefix, PathSuffix)
         end,
         end,
 
 
-    HeadersTemplate1 = maps:get(headers, Request),
-    HeadersTemplate2 = maps:get(headers, ActionState),
-    Headers = merge_proplist(
-        render_headers(HeadersTemplate1, RenderTmplFunc, Msg),
-        render_headers(HeadersTemplate2, RenderTmplFunc, Msg)
+    ActionHaders = maps:get(headers, ActionState),
+    BaseHeaders = maps:get(headers, Request),
+    Headers = merge_headers(
+        render_headers(ActionHaders, RenderTmplFunc, Msg),
+        render_headers(BaseHeaders, RenderTmplFunc, Msg)
     ),
     ),
     BodyTemplate = maps:get(body, ActionState),
     BodyTemplate = maps:get(body, ActionState),
     Body = render_request_body(BodyTemplate, RenderTmplFunc, Msg),
     Body = render_request_body(BodyTemplate, RenderTmplFunc, Msg),
@@ -769,19 +769,11 @@ process_request_and_action(Request, ActionState, Msg) ->
         request_timeout => maps:get(request_timeout, ActionState)
         request_timeout => maps:get(request_timeout, ActionState)
     }.
     }.
 
 
-merge_proplist(Proplist1, Proplist2) ->
-    lists:foldl(
-        fun({K, V}, Acc) ->
-            case lists:keyfind(K, 1, Acc) of
-                false ->
-                    [{K, V} | Acc];
-                {K, _} = {K, V1} ->
-                    [{K, V1} | Acc]
-            end
-        end,
-        Proplist2,
-        Proplist1
-    ).
+merge_headers([], Result) ->
+    Result;
+merge_headers([{K, V} | Rest], Result) ->
+    R = lists:keydelete(K, 1, Result),
+    merge_headers(Rest, [{K, V} | R]).
 
 
 process_request(
 process_request(
     #{
     #{

+ 31 - 6
apps/emqx_bridge_http/test/emqx_bridge_http_v2_SUITE.erl

@@ -132,9 +132,14 @@ t_update_with_sensitive_data(Config) ->
             AuthHeader = <<"Bearer some_token">>,
             AuthHeader = <<"Bearer some_token">>,
             ConnectorCfg1 = emqx_utils_maps:deep_merge(
             ConnectorCfg1 = emqx_utils_maps:deep_merge(
                 ConnectorCfg0,
                 ConnectorCfg0,
-                #{<<"headers">> => #{<<"authorization">> => AuthHeader}}
+                #{
+                    <<"headers">> => #{
+                        <<"authorization">> => AuthHeader,
+                        <<"x-test-header">> => <<"from-connector">>
+                    }
+                }
             ),
             ),
-            ActionCfg = make_action_config(Config),
+            ActionCfg = make_action_config(Config, #{<<"x-test-header">> => <<"from-action">>}),
             CreateConfig = [
             CreateConfig = [
                 {bridge_kind, action},
                 {bridge_kind, action},
                 {action_type, ?BRIDGE_TYPE},
                 {action_type, ?BRIDGE_TYPE},
@@ -156,7 +161,14 @@ t_update_with_sensitive_data(Config) ->
                 }
                 }
             ),
             ),
             emqx:publish(emqx_message:make(<<"t/http">>, <<"1">>)),
             emqx:publish(emqx_message:make(<<"t/http">>, <<"1">>)),
-            ?assertReceive({http, #{<<"authorization">> := AuthHeader}, _}),
+            ?assertReceive(
+                {http,
+                    #{
+                        <<"authorization">> := AuthHeader,
+                        <<"x-test-header">> := <<"from-action">>
+                    },
+                    _}
+            ),
 
 
             %% Now update the connector and see if the header stays deobfuscated.  We send the old
             %% Now update the connector and see if the header stays deobfuscated.  We send the old
             %% auth header as an obfuscated value to simulate the behavior of the frontend.
             %% auth header as an obfuscated value to simulate the behavior of the frontend.
@@ -165,6 +177,8 @@ t_update_with_sensitive_data(Config) ->
                 #{
                 #{
                     <<"headers">> => #{
                     <<"headers">> => #{
                         <<"authorization">> => Obfuscated,
                         <<"authorization">> => Obfuscated,
+                        <<"x-test-header">> => <<"from-connector-new">>,
+                        <<"x-test-header-2">> => <<"from-connector-new">>,
                         <<"other_header">> => <<"new">>
                         <<"other_header">> => <<"new">>
                     }
                     }
                 }
                 }
@@ -177,8 +191,16 @@ t_update_with_sensitive_data(Config) ->
 
 
             emqx:publish(emqx_message:make(<<"t/http">>, <<"2">>)),
             emqx:publish(emqx_message:make(<<"t/http">>, <<"2">>)),
             %% Should not be obfuscated.
             %% Should not be obfuscated.
-            ?assertReceive({http, #{<<"authorization">> := AuthHeader}, _}, 2_000),
-
+            ?assertReceive(
+                {http,
+                    #{
+                        <<"authorization">> := AuthHeader,
+                        <<"x-test-header">> := <<"from-action">>,
+                        <<"x-test-header-2">> := <<"from-connector-new">>
+                    },
+                    _},
+                2_000
+            ),
             ok
             ok
         end,
         end,
         []
         []
@@ -204,6 +226,9 @@ make_connector_config(Config) ->
     }.
     }.
 
 
 make_action_config(Config) ->
 make_action_config(Config) ->
+    make_action_config(Config, _Headers = #{}).
+
+make_action_config(Config, Headers) ->
     Path = ?config(path, Config),
     Path = ?config(path, Config),
     #{
     #{
         <<"enable">> => true,
         <<"enable">> => true,
@@ -211,7 +236,7 @@ make_action_config(Config) ->
         <<"parameters">> => #{
         <<"parameters">> => #{
             <<"path">> => Path,
             <<"path">> => Path,
             <<"method">> => <<"post">>,
             <<"method">> => <<"post">>,
-            <<"headers">> => #{},
+            <<"headers">> => Headers,
             <<"body">> => <<"${.}">>
             <<"body">> => <<"${.}">>
         },
         },
         <<"resource_opts">> => #{
         <<"resource_opts">> => #{