This is an automated email from the ASF dual-hosted git repository.

liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 5cdc8582c6 [type:fix] fix duplicate header for request plugin (#5846)
5cdc8582c6 is described below

commit 5cdc8582c68b815b495a1fbd4ce3a3b4f9ce604c
Author: moremind <[email protected]>
AuthorDate: Sat Dec 14 13:37:40 2024 +0800

    [type:fix] fix duplicate header for request plugin (#5846)
    
    * [type:fix] fix client register validation
    
    * [type:fix] fix rqeuest header
    
    * [type:fix] fix rqeuest header
    
    * [type:fix] fix rqeuest header
    
    * [type:fix] fix duplicate header for request plugin
    
    * [type:fix] fix duplicate header for request plugin
    
    * [type:fix] fix duplicate header for request plugin
    
    * [type:fix] fix duplicate header for request plugin
---
 db/init/mysql/schema.sql                           |   7 ++
 db/init/ob/schema.sql                              |   8 +-
 db/init/og/create-table.sql                        |   7 ++
 db/init/oracle/schema.sql                          |  22 +++++
 db/init/pg/create-table.sql                        |   7 ++
 db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql           |   9 +-
 db/upgrade/2.6.1-upgrade-2.7.0-og.sql              |   8 +-
 db/upgrade/2.6.1-upgrade-2.7.0-oracle.sql          |  22 +++++
 db/upgrade/2.6.1-upgrade-2.7.0-pg.sql              |   7 ++
 .../src/main/resources/sql-script/h2/schema.sql    |   5 +
 .../src/main/resources/application.yml             |   4 -
 .../apache/shenyu/common/constant/Constants.java   |   5 +
 .../common/dto/convert/rule/RequestHandle.java     | 101 +++++++++++++++++++++
 .../common/enums/HeaderUniqueStrategyEnum.java     |  39 ++++++++
 .../shenyu/common/enums/UniqueHeaderEnum.java      |  41 +++++++++
 .../httpclient/AbstractHttpClientPlugin.java       |  22 ++++-
 .../plugin/httpclient/NettyHttpClientPlugin.java   |  34 +++----
 .../shenyu/plugin/httpclient/WebClientPlugin.java  |  32 +++----
 .../config/DuplicateResponseHeaderProperties.java  |  90 ------------------
 .../httpclient/NettyHttpClientPluginTest.java      |   3 +-
 .../plugin/httpclient/WebClientPluginTest.java     |  11 +--
 .../shenyu/plugin/request/RequestPlugin.java       |  17 +++-
 .../httpclient/HttpClientPluginConfiguration.java  |  22 +----
 23 files changed, 355 insertions(+), 168 deletions(-)

diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index 041e0cdd65..1d88800a6e 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -1293,6 +1293,11 @@ INSERT INTO `plugin_handle` VALUES 
('1722804548510507023', '3', 'rewriteMetaData
 INSERT INTO `plugin_handle` VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO `plugin_handle` VALUES ('1722804548510507025', '8', 'serverLists', 
'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', '2024-08-24 
21:53:27.483');
 INSERT INTO `plugin_handle` VALUES ('1722804548510507026', '8', 'props', 
'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 21:53:30.255');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 -- ----------------------------
 -- Table structure for resource
@@ -2079,6 +2084,8 @@ INSERT INTO `shenyu_dict` VALUES ('1679002911061737474', 
'discoveryMode', 'DISCO
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737475', 'discoveryMode', 
'DISCOVERY_MODE', 'eureka', '{"eurekaClientRefreshInterval": "10", 
"eurekaClientRegistryFetchIntervalSeconds": "10"}', 'discoery mode to link 
eureka', 0, 1,'2023-03-01 10:48:49', '2023-03-01 10:48:49');
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737478', 'rewriteMetaData', 
'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737479', 'rewriteMetaData', 
'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737480', 'preserveHost', 
'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-12-05 22:00:46.416', 
'2024-12-05 22:00:46.416');
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737481', 'preserveHost', 
'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-12-05 22:01:13.396', 
'2024-12-05 22:01:13.396');
 
 -- ----------------------------
 -- Table structure for user_role
diff --git a/db/init/ob/schema.sql b/db/init/ob/schema.sql
index cd6ff2b36c..cf0790759a 100644
--- a/db/init/ob/schema.sql
+++ b/db/init/ob/schema.sql
@@ -1286,6 +1286,11 @@ INSERT INTO `plugin_handle` VALUES 
('1722804548510507023', '3', 'rewriteMetaData
 INSERT INTO `plugin_handle` VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO `plugin_handle` VALUES ('1722804548510507025', '8', 'serverLists', 
'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', '2024-08-24 
21:53:27.483');
 INSERT INTO `plugin_handle` VALUES ('1722804548510507026', '8', 'props', 
'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 21:53:30.255');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 -- ----------------------------
 -- Table structure for resource
@@ -2066,7 +2071,8 @@ INSERT INTO `shenyu_dict` VALUES ('1679002911061737474', 
'discoveryMode', 'DISCO
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737475', 'discoveryMode', 
'DISCOVERY_MODE', 'eureka', '{"eurekaClientRefreshInterval": "10", 
"eurekaClientRegistryFetchIntervalSeconds": "10"}', 'discoery mode to link 
eureka', 0, 1,'2023-03-01 10:48:49', '2023-03-01 10:48:49');
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737478', 'rewriteMetaData', 
'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737479', 'rewriteMetaData', 
'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
-
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737480', 'preserveHost', 
'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-12-05 22:00:46.416', 
'2024-12-05 22:00:46.416');
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737481', 'preserveHost', 
'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-12-05 22:01:13.396', 
'2024-12-05 22:01:13.396');
 -- ----------------------------
 -- Table structure for user_role
 -- ----------------------------
diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql
index 74576c5ecf..4fed467321 100644
--- a/db/init/og/create-table.sql
+++ b/db/init/og/create-table.sql
@@ -1370,6 +1370,11 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1722804548510507023', '3', 'rewrit
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507025', '8', 
'serverLists', 'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', 
'2024-08-24 21:53:27.483');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507026', '8', 
'props', 'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 
21:53:30.255');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 -- ----------------------------
 -- Table structure for resource
@@ -2152,6 +2157,8 @@ INSERT INTO "public"."shenyu_dict" VALUES 
('1679002911061737474', 'discoveryMode
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737475', 
'discoveryMode', 'DISCOVERY_MODE', 'eureka', '{"eurekaClientRefreshInterval": 
"10", "eurekaClientRegistryFetchIntervalSeconds": "10"}', 'discoery mode to 
link eureka', 0, 1,'2023-03-01 10:48:49', '2023-03-01 10:48:49');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737478', 
'rewriteMetaData', 'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737479', 
'rewriteMetaData', 'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737480', 
'preserveHost', 'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737481', 
'preserveHost', 'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 
 -- ----------------------------
 -- Table structure for user_role
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 1ec2dde1cf..22463a224e 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -2176,6 +2176,23 @@ values ('1722804548510507025', '8', 'serverLists', 
'serverLists', 2, 3, 2, NULL)
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1722804548510507026', '8', 'props', 'props', 4, 3, 3, NULL);
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507027', '20', 'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507028', '20', 'requestHeaderUniqueStrategy', 
'requestHeaderUniqueStrategy', 2, 2, 1, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507029', '20', 'requestUniqueHeaders', 
'requestUniqueHeaders', 2, 2, 2, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 
'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 
2, 2, 4, '{"required":"0","rule":""}');
+
+
+
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
 VALUES ('1529402613195784272', 'securityProtocol', 'SECURITY_PROTOCOL', 
'PLAINTEXT', 'PLAINTEXT', '', 1, 1);
 
@@ -2245,6 +2262,11 @@ VALUES ('1679002911061737474', 'discoveryMode', 
'DISCOVERY_MODE', 'nacos', '{"gr
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
 VALUES ('1679002911061737475', 'discoveryMode', 'DISCOVERY_MODE', 'eureka', 
'{"eurekaClientRefreshInterval": "10", 
"eurekaClientRegistryFetchIntervalSeconds": "10"}', 'discoery mode to link 
eureka', 0, 1);
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
+VALUES ('1679002911061737480', 'preserveHost', 'PRESERVE_HOST', 'true', 
'true', '', 0, 1);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
+VALUES('1679002911061737481', 'preserveHost', 'PRESERVE_HOST', 'false', 
'false', '', 1, 1);
 
 
 /** insert resource for resource */
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index 8d4ba5008f..b49dc04cc5 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -1430,6 +1430,11 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1722804548510507023', '3', 'rewrit
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507025', '8', 
'serverLists', 'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', 
'2024-08-24 21:53:27.483');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507026', '8', 
'props', 'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 
21:53:30.255');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 -- ----------------------------
 -- Table structure for resource
@@ -2279,6 +2284,8 @@ INSERT INTO "public"."shenyu_dict" VALUES 
('1679002911061737474', 'discoveryMode
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737475', 
'discoveryMode', 'DISCOVERY_MODE', 'eureka', '{"eurekaClientRefreshInterval": 
"10", "eurekaClientRegistryFetchIntervalSeconds": "10"}', 'discoery mode to 
link eureka', 0, 1,'2023-03-17 10:15:16.846', '2023-03-07 10:15:16.846');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737478', 
'rewriteMetaData', 'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737479', 
'rewriteMetaData', 'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737480', 
'preserveHost', 'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737481', 
'preserveHost', 'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 
 -- ----------------------------
 -- Table structure for user_role
diff --git a/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql 
b/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
index 54845ebd1f..df100e302f 100755
--- a/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
+++ b/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
@@ -23,9 +23,16 @@ INSERT INTO `plugin_handle` VALUES ('1722804548510507024', 
'8', 'registerType',
 INSERT INTO `plugin_handle` VALUES ('1722804548510507025', '8', 'serverLists', 
'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', '2024-08-24 
21:53:27.483');
 INSERT INTO `plugin_handle` VALUES ('1722804548510507026', '8', 'props', 
'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 21:53:30.255');
 
+INSERT INTO `plugin_handle` VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO `plugin_handle` VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
+
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737478', 'rewriteMetaData', 
'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
 INSERT INTO `shenyu_dict` VALUES ('1679002911061737479', 'rewriteMetaData', 
'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 14:31:49', 
'2024-02-07 14:31:49');
-
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737480', 'preserveHost', 
'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-12-05 22:00:46.416', 
'2024-12-05 22:00:46.416');
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737481', 'preserveHost', 
'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-12-05 22:01:13.396', 
'2024-12-05 22:01:13.396');
 -- ----------------------------
 -- Table structure for sheny_lock
 -- ----------------------------
diff --git a/db/upgrade/2.6.1-upgrade-2.7.0-og.sql 
b/db/upgrade/2.6.1-upgrade-2.7.0-og.sql
index ab092557bd..1f27167d0b 100644
--- a/db/upgrade/2.6.1-upgrade-2.7.0-og.sql
+++ b/db/upgrade/2.6.1-upgrade-2.7.0-og.sql
@@ -21,10 +21,16 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1722804548510507022', '3', 'rewrit
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507025', '8', 
'serverLists', 'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', 
'2024-08-24 21:53:27.483');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507026', '8', 
'props', 'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 
21:53:30.255');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737478', 
'rewriteMetaData', 'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737479', 
'rewriteMetaData', 'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
-
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737480', 
'preserveHost', 'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737481', 
'preserveHost', 'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 -- ----------------------------
 -- Table structure for shenyu_lock
 -- ----------------------------
diff --git a/db/upgrade/2.6.1-upgrade-2.7.0-oracle.sql 
b/db/upgrade/2.6.1-upgrade-2.7.0-oracle.sql
index cf86c37039..03bf078847 100755
--- a/db/upgrade/2.6.1-upgrade-2.7.0-oracle.sql
+++ b/db/upgrade/2.6.1-upgrade-2.7.0-oracle.sql
@@ -21,6 +21,12 @@ VALUES ('1679002911061737478', 'rewriteMetaData', 
'REWRITE_META_DATA', 'true', '
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ INTO SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
 VALUES ('1679002911061737479', 'rewriteMetaData', 'REWRITE_META_DATA', 
'false', 'false', '', 4, 1);
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
+VALUES ('1679002911061737480', 'preserveHost', 'PRESERVE_HOST', 'true', 
'true', '', 0, 1);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
+VALUES('1679002911061737481', 'preserveHost', 'PRESERVE_HOST', 'false', 
'false', '', 1, 1);
+
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1722804548510507020', '14', 'rewriteContextPath', 
'rewriteContextPath', 2, 2, 2, '{"required":"0","defaultValue":""}');
 
@@ -39,6 +45,22 @@ values ('1722804548510507025', '8', 'serverLists', 
'serverLists', 2, 3, 2, NULL)
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1722804548510507026', '8', 'props', 'props', 4, 3, 3, NULL);
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507027', '20', 'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507028', '20', 'requestHeaderUniqueStrategy', 
'requestHeaderUniqueStrategy', 2, 2, 1, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507029', '20', 'requestUniqueHeaders', 
'requestUniqueHeaders', 2, 2, 2, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 
'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 
2, 2, 4, '{"required":"0","rule":""}');
+
+
 -- ----------------------------
 -- Table structure for SHENYU_LOCK
 -- ----------------------------
diff --git a/db/upgrade/2.6.1-upgrade-2.7.0-pg.sql 
b/db/upgrade/2.6.1-upgrade-2.7.0-pg.sql
index d834e9a3e4..71c2ca5c3a 100755
--- a/db/upgrade/2.6.1-upgrade-2.7.0-pg.sql
+++ b/db/upgrade/2.6.1-upgrade-2.7.0-pg.sql
@@ -21,9 +21,16 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1722804548510507022', '3', 'rewrit
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507024', '8', 
'registerType', 'registerType', 2, 3, 1, NULL, '2024-08-24 09:40:03.293', 
'2024-08-24 21:52:27.920');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507025', '8', 
'serverLists', 'serverLists', 2, 3, 2, NULL, '2024-08-24 21:52:51.179', 
'2024-08-24 21:53:27.483');
 INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507026', '8', 
'props', 'props', 4, 3, 3, NULL, '2024-08-24 21:53:25.764', '2024-08-24 
21:53:30.255');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507027', '20', 
'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}', '2024-12-05 22:00:02.251', 
'2024-12-05 22:00:02.251');
 
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737478', 
'rewriteMetaData', 'REWRITE_META_DATA', 'true', 'true', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
 INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737479', 
'rewriteMetaData', 'REWRITE_META_DATA', 'false', 'false', '', 4, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737480', 
'preserveHost', 'PRESERVE_HOST', 'true', 'true', '', 0, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."shenyu_dict" VALUES ('1679002911061737481', 
'preserveHost', 'PRESERVE_HOST', 'false', 'false', '', 1, 1, '2024-02-07 
14:31:49', '2024-02-07 14:31:49');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507028', '20', 
'requestHeaderUniqueStrategy', 'requestHeaderUniqueStrategy', 2, 2, 1, 
'{"required":"0","rule":""}', '2024-12-13 22:36:54.299', '2024-12-13 
22:36:54.299');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 
'requestUniqueHeaders', 'requestUniqueHeaders', 2, 2, 2, 
'{"required":"0","rule":""}', '2024-12-13 22:37:29.959', '2024-12-13 
22:37:29.959');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 
'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, 
'{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 
22:37:48.239');
+INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 
'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, 
'{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 
22:38:05.726');
 
 -- ----------------------------
 -- Table structure for shenyu_lock
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql 
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index efe0acebc2..38c16b23ae 100755
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -918,6 +918,11 @@ INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507024', '8', 'registerType', 'registerType', 2, 3, 1, NULL);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507025', '8', 'serverLists', 'serverLists', 2, 3, 2, NULL);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507026', '8', 'props', 'props', 4, 3, 3, NULL);
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507027', '20', 'preserveHost', 'preserveHost', 3, 2, 0, 
'{"required":"0","defaultValue":"false","rule":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507028', '20', 'requestHeaderUniqueStrategy', 
'requestHeaderUniqueStrategy', 2, 2, 1, '{"required":"0","rule":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507029', '20', 'requestUniqueHeaders', 'requestUniqueHeaders', 
2, 2, 2, '{"required":"0","rule":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507030', '20', 'respHeaderUniqueStrategy', 
'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1722804548510507031', '8', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 
2, 4, '{"required":"0","rule":""}');
 
 /** insert resource for resource */
 INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`, 
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`, 
`status`) 
VALUES('1346775491550474240','','SHENYU.MENU.PLUGIN.LIST','plug','/plug','PluginList','0','0','dashboard','0','0','','1');
diff --git a/shenyu-bootstrap/src/main/resources/application.yml 
b/shenyu-bootstrap/src/main/resources/application.yml
index 18fbbf7880..f852f0c14a 100644
--- a/shenyu-bootstrap/src/main/resources/application.yml
+++ b/shenyu-bootstrap/src/main/resources/application.yml
@@ -193,10 +193,6 @@ shenyu:
 #      selectCount: 1
 #      workerCount: 8
 #      daemon: true
-  duplicate-response-header:
-    strategy: RETAIN_FIRST
-    headers:
-      - Access-Control-Allow-Origin
   register:
     enabled: false
     registerType: zookeeper #etcd #consul
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java 
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
index 77b0251588..3cd0c7d16f 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
@@ -925,6 +925,11 @@ public interface Constants {
      * The constant EVENT_NAME_REGISTER.
      */
     String HTTP_PATH = "shenyu.httpPath";
+
+    /**
+     * The constant preserve host.
+     */
+    String PRESERVE_HOST = "preserveHost";
     
     /**
      * String q.
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/RequestHandle.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/RequestHandle.java
index 97b5872517..e53a9cb141 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/RequestHandle.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/RequestHandle.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.common.dto.convert.rule;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
+import org.apache.shenyu.common.enums.HeaderUniqueStrategyEnum;
 
 import java.util.Map;
 import java.util.Objects;
@@ -35,6 +36,16 @@ public class RequestHandle {
 
     private ShenyuCookie cookie;
 
+    private Boolean preserveHost = Boolean.FALSE;
+
+    private HeaderUniqueStrategyEnum requestHeaderUniqueStrategy = 
HeaderUniqueStrategyEnum.RETAIN_FIRST;
+
+    private String requestUniqueHeaders;
+
+    private HeaderUniqueStrategyEnum respHeaderUniqueStrategy = 
HeaderUniqueStrategyEnum.RETAIN_FIRST;
+
+    private String respUniqueHeaders;
+
     /**
      * get header.
      *
@@ -89,6 +100,96 @@ public class RequestHandle {
         this.cookie = cookie;
     }
 
+    /**
+     * get preserveHost.
+     *
+     * @return preserveHost
+     */
+    public Boolean getPreserveHost() {
+        return preserveHost;
+    }
+
+    /**
+     * set preserveHost.
+     *
+     * @param preserveHost preserveHost
+     */
+    public void setPreserveHost(final Boolean preserveHost) {
+        this.preserveHost = preserveHost;
+    }
+
+    /**
+     * get headerUniqueStrategy.
+     *
+     * @return headerUniqueStrategy
+     */
+    public HeaderUniqueStrategyEnum getRequestHeaderUniqueStrategy() {
+        return requestHeaderUniqueStrategy;
+    }
+
+    /**
+     * set headerUniqueStrategy.
+     *
+     * @param requestHeaderUniqueStrategy requestHeaderUniqueStrategy
+     */
+    public void setRequestHeaderUniqueStrategy(final HeaderUniqueStrategyEnum 
requestHeaderUniqueStrategy) {
+        this.requestHeaderUniqueStrategy = requestHeaderUniqueStrategy;
+    }
+
+    /**
+     * get uniqueHeader.
+     *
+     * @return uniqueHeader
+     */
+    public String getRequestUniqueHeaders() {
+        return requestUniqueHeaders;
+    }
+
+    /**
+     * set uniqueHeader.
+     *
+     * @param requestUniqueHeaders requestUniqueHeaders
+     */
+    public void setRequestUniqueHeaders(final String requestUniqueHeaders) {
+        this.requestUniqueHeaders = requestUniqueHeaders;
+    }
+
+    /**
+     * get respHeaderUniqueStrategy.
+     *
+     * @return respHeaderUniqueStrategy
+     */
+    public HeaderUniqueStrategyEnum getRespHeaderUniqueStrategy() {
+        return respHeaderUniqueStrategy;
+    }
+
+    /**
+     * set respHeaderUniqueStrategy.
+     *
+     * @param respHeaderUniqueStrategy respHeaderUniqueStrategy
+     */
+    public void setRespHeaderUniqueStrategy(final HeaderUniqueStrategyEnum 
respHeaderUniqueStrategy) {
+        this.respHeaderUniqueStrategy = respHeaderUniqueStrategy;
+    }
+
+    /**
+     * get respUniqueHeaders.
+     *
+     * @return respUniqueHeaders
+     */
+    public String getRespUniqueHeaders() {
+        return respUniqueHeaders;
+    }
+
+    /**
+     * set respUniqueHeaders.
+     *
+     * @param respUniqueHeaders respUniqueHeaders
+     */
+    public void setRespUniqueHeaders(final String respUniqueHeaders) {
+        this.respUniqueHeaders = respUniqueHeaders;
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HeaderUniqueStrategyEnum.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HeaderUniqueStrategyEnum.java
new file mode 100644
index 0000000000..4ed8b119f6
--- /dev/null
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/HeaderUniqueStrategyEnum.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.enums;
+
+/**
+ * Gets duplicate response headers handle strategy.
+ */
+public enum HeaderUniqueStrategyEnum {
+
+    /**
+     * Default: Retain the first value only.
+     */
+    RETAIN_FIRST,
+
+    /**
+     * Retain the last value only.
+     */
+    RETAIN_LAST,
+
+    /**
+     * Retain all unique values in the order of their first encounter.
+     */
+    RETAIN_UNIQUE
+}
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/UniqueHeaderEnum.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/UniqueHeaderEnum.java
new file mode 100644
index 0000000000..cc06680d5e
--- /dev/null
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/UniqueHeaderEnum.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.enums;
+
+public enum UniqueHeaderEnum {
+    REQ_UNIQUE_HEADER("requestUniqueHeaders", "requestHeaderUniqueStrategy"),
+
+    RESP_UNIQUE_HEADER("responseUniqueHeaders", 
"responseHeaderUniqueStrategy");
+
+    private final String name;
+
+    private final String strategy;
+
+    UniqueHeaderEnum(final String name, final String strategy) {
+        this.name = name;
+        this.strategy = strategy;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getStrategy() {
+        return strategy;
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
index a7e3befe9a..69ba3c364a 100644
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/AbstractHttpClientPlugin.java
@@ -21,8 +21,11 @@ import com.google.common.collect.Sets;
 import io.netty.channel.ConnectTimeoutException;
 import io.netty.handler.timeout.ReadTimeoutException;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.enums.HeaderUniqueStrategyEnum;
 import org.apache.shenyu.common.enums.RetryEnum;
+import org.apache.shenyu.common.enums.UniqueHeaderEnum;
 import org.apache.shenyu.common.exception.ShenyuException;
 import org.apache.shenyu.common.utils.LogUtils;
 import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
@@ -35,7 +38,6 @@ import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
 import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
 import org.apache.shenyu.plugin.api.utils.RequestUrlUtils;
 import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties.DuplicateResponseHeaderStrategy;
 import org.apache.shenyu.plugin.httpclient.exception.ShenyuTimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,6 +54,7 @@ import reactor.util.retry.RetryBackoffSpec;
 import java.net.URI;
 import java.time.Duration;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Objects;
@@ -171,8 +174,23 @@ public abstract class AbstractHttpClientPlugin<R> 
implements ShenyuPlugin {
      */
     protected abstract Mono<R> doRequest(ServerWebExchange exchange, String 
httpMethod,
                                          URI uri, Flux<DataBuffer> body);
+
+    protected void duplicateHeaders(final ServerWebExchange exchange, final 
HttpHeaders headers, final UniqueHeaderEnum uniqueHeaderEnum) {
+        final String duplicateHeader = 
exchange.getAttribute(uniqueHeaderEnum.getName());
+        if (StringUtils.isEmpty(duplicateHeader)) {
+            return;
+        }
+        List<String> duplicateHeaderList = 
Arrays.asList(StringUtils.split(duplicateHeader, Constants.SEPARATOR_CHARS));
+        if (CollectionUtils.isEmpty(duplicateHeaderList)) {
+            return;
+        }
+        HeaderUniqueStrategyEnum strategy = 
exchange.getAttributeOrDefault(uniqueHeaderEnum.getStrategy(), 
HeaderUniqueStrategyEnum.RETAIN_FIRST);
+        for (String headerKey : duplicateHeaderList) {
+            this.duplicate(headers, headerKey, strategy);
+        }
+    }
     
-    protected void duplicateHeaders(final HttpHeaders headers, final String 
header, final DuplicateResponseHeaderStrategy strategy) {
+    protected void duplicate(final HttpHeaders headers, final String header, 
final HeaderUniqueStrategyEnum strategy) {
         List<String> headerValues = headers.get(header);
         if (Objects.isNull(headerValues) || headerValues.size() <= 1) {
             return;
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPlugin.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPlugin.java
index 528878e3ba..a0c135ebc7 100644
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPlugin.java
@@ -18,17 +18,17 @@
 package org.apache.shenyu.plugin.httpclient;
 
 import io.netty.handler.codec.http.HttpMethod;
-import org.apache.commons.collections4.CollectionUtils;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.enums.PluginEnum;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties.DuplicateResponseHeaderStrategy;
+import org.apache.shenyu.common.enums.UniqueHeaderEnum;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.core.io.buffer.NettyDataBuffer;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.server.reactive.AbstractServerHttpResponse;
+import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Flux;
@@ -37,7 +37,6 @@ import reactor.netty.http.client.HttpClient;
 import reactor.netty.http.client.HttpClientResponse;
 
 import java.net.URI;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -47,25 +46,28 @@ public class NettyHttpClientPlugin extends 
AbstractHttpClientPlugin<HttpClientRe
 
     private final HttpClient httpClient;
 
-    private final DuplicateResponseHeaderProperties properties;
-
     /**
      * Instantiates a new Netty http client plugin.
      *
      * @param httpClient the http client
-     * @param properties proerties
      */
-    public NettyHttpClientPlugin(final HttpClient httpClient, final 
DuplicateResponseHeaderProperties properties) {
+    public NettyHttpClientPlugin(final HttpClient httpClient) {
         this.httpClient = httpClient;
-        this.properties = properties;
     }
 
     @Override
     protected Mono<HttpClientResponse> doRequest(final ServerWebExchange 
exchange, final String httpMethod,
                                                  final URI uri, final 
Flux<DataBuffer> body) {
+        ServerHttpRequest request = exchange.getRequest();
+        final HttpHeaders httpHeaders = new HttpHeaders(request.getHeaders());
+        this.duplicateHeaders(exchange, httpHeaders, 
UniqueHeaderEnum.REQ_UNIQUE_HEADER);
         return Mono.from(httpClient.headers(headers -> {
-            exchange.getRequest().getHeaders().forEach(headers::add);
+            httpHeaders.forEach(headers::set);
             headers.remove(HttpHeaders.HOST);
+            Boolean preserveHost = 
exchange.getAttributeOrDefault(Constants.PRESERVE_HOST, Boolean.FALSE);
+            if (preserveHost) {
+                headers.add(HttpHeaders.HOST, 
request.getHeaders().getFirst(HttpHeaders.HOST));
+            }
         }).request(HttpMethod.valueOf(httpMethod)).uri(uri.toASCIIString())
                 .send((req, nettyOutbound) -> 
nettyOutbound.send(body.map(dataBuffer -> ((NettyDataBuffer) 
dataBuffer).getNativeBuffer())))
                 .responseConnection((res, connection) -> {
@@ -74,7 +76,7 @@ public class NettyHttpClientPlugin extends 
AbstractHttpClientPlugin<HttpClientRe
                     final ServerHttpResponse response = exchange.getResponse();
                     HttpHeaders headers = new HttpHeaders();
                     res.responseHeaders().forEach(entry -> 
headers.add(entry.getKey(), entry.getValue()));
-                    this.duplicate(headers);
+                    this.duplicateHeaders(exchange, httpHeaders, 
UniqueHeaderEnum.RESP_UNIQUE_HEADER);
                     String contentTypeValue = 
headers.getFirst(HttpHeaders.CONTENT_TYPE);
                     if (StringUtils.isNotBlank(contentTypeValue)) {
                         
exchange.getAttributes().put(Constants.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, 
contentTypeValue);
@@ -92,16 +94,6 @@ public class NettyHttpClientPlugin extends 
AbstractHttpClientPlugin<HttpClientRe
                 }));
     }
 
-    private void duplicate(final HttpHeaders headers) {
-        List<String> duplicateHeaders = properties.getHeaders();
-        if (CollectionUtils.isEmpty(duplicateHeaders)) {
-            return;
-        }
-        DuplicateResponseHeaderStrategy strategy = properties.getStrategy();
-        for (String headerKey : duplicateHeaders) {
-            duplicateHeaders(headers, headerKey, strategy);
-        }
-    }
 
     @Override
     public int getOrder() {
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
index b12cd81169..0e8d6a545a 100644
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
@@ -17,26 +17,24 @@
 
 package org.apache.shenyu.plugin.httpclient;
 
-import org.apache.commons.collections4.CollectionUtils;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.common.enums.ResultEnum;
+import org.apache.shenyu.common.enums.UniqueHeaderEnum;
 import org.apache.shenyu.plugin.base.utils.MediaTypeUtils;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties.DuplicateResponseHeaderStrategy;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.web.reactive.function.client.WebClient;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 import java.net.URI;
-import java.util.List;
 
 /**
  * The type Web client plugin.
@@ -44,18 +42,14 @@ import java.util.List;
 public class WebClientPlugin extends 
AbstractHttpClientPlugin<ResponseEntity<Flux<DataBuffer>>> {
     
     private final WebClient webClient;
-    
-    private final DuplicateResponseHeaderProperties properties;
 
     /**
      * Instantiates a new Web client plugin.
      *
      * @param webClient the web client
-     * @param properties properties
      */
-    public WebClientPlugin(final WebClient webClient, final 
DuplicateResponseHeaderProperties properties) {
+    public WebClientPlugin(final WebClient webClient) {
         this.webClient = webClient;
-        this.properties = properties;
     }
     
     @Override
@@ -64,10 +58,17 @@ public class WebClientPlugin extends 
AbstractHttpClientPlugin<ResponseEntity<Flu
         // springWebflux5.3 mark #exchange() deprecated. because #echange 
maybe make memory leak.
         // https://github.com/spring-projects/spring-framework/issues/25751
         // exchange is deprecated, so change to {@link 
WebClient.RequestHeadersSpec#exchangeToMono(Function)}
+        ServerHttpRequest request = exchange.getRequest();
+        final HttpHeaders httpHeaders = new HttpHeaders(request.getHeaders());
+        this.duplicateHeaders(exchange, httpHeaders, 
UniqueHeaderEnum.REQ_UNIQUE_HEADER);
         final WebClient.ResponseSpec responseSpec = 
webClient.method(HttpMethod.valueOf(httpMethod)).uri(uri)
                 .headers(headers -> {
                     headers.addAll(exchange.getRequest().getHeaders());
                     headers.remove(HttpHeaders.HOST);
+                    Boolean preserveHost = 
exchange.getAttributeOrDefault(Constants.PRESERVE_HOST, Boolean.FALSE);
+                    if (preserveHost) {
+                        headers.add(HttpHeaders.HOST, 
request.getHeaders().getFirst(HttpHeaders.HOST));
+                    }
                 })
                 .body((outputMessage, context) -> {
                     MediaType mediaType = 
exchange.getRequest().getHeaders().getContentType();
@@ -89,24 +90,13 @@ public class WebClientPlugin extends 
AbstractHttpClientPlugin<ResponseEntity<Flu
                     }
                     HttpHeaders headers = new HttpHeaders();
                     headers.addAll(fluxResponseEntity.getHeaders());
-                    this.duplicate(headers);
+                    this.duplicateHeaders(exchange, headers, 
UniqueHeaderEnum.RESP_UNIQUE_HEADER);
                     exchange.getResponse().getHeaders().putAll(headers);
                     
exchange.getResponse().setStatusCode(fluxResponseEntity.getStatusCode());
                     
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_ATTR, 
fluxResponseEntity);
                     return Mono.just(fluxResponseEntity);
                 });
     }
-    
-    private void duplicate(final HttpHeaders headers) {
-        List<String> duplicateHeaders = properties.getHeaders();
-        if (CollectionUtils.isEmpty(duplicateHeaders)) {
-            return;
-        }
-        DuplicateResponseHeaderStrategy strategy = properties.getStrategy();
-        for (String headerKey : duplicateHeaders) {
-            duplicateHeaders(headers, headerKey, strategy);
-        }
-    }
 
     @Override
     public int getOrder() {
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/config/DuplicateResponseHeaderProperties.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/config/DuplicateResponseHeaderProperties.java
deleted file mode 100644
index 3dbbdfc610..0000000000
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/config/DuplicateResponseHeaderProperties.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shenyu.plugin.httpclient.config;
-
-import java.util.List;
-
-public class DuplicateResponseHeaderProperties {
-    
-    /**
-     * Duplicate response headers.
-     */
-    private List<String> headers;
-    
-    /**
-     * Duplicate response headers handle strategy.
-     */
-    private DuplicateResponseHeaderStrategy strategy = 
DuplicateResponseHeaderStrategy.RETAIN_FIRST;
-    
-    /**
-     * Gets duplicate response headers.
-     *
-     * @return duplicate response headers
-     */
-    public List<String> getHeaders() {
-        return headers;
-    }
-    
-    /**
-     * Sets duplicate response headers.
-     *
-     * @param headers duplicate response headers
-     */
-    public void setHeaders(final List<String> headers) {
-        this.headers = headers;
-    }
-    
-    /**
-     * Gets duplicate response headers handle strategy.
-     *
-     * @return duplicate response headers handle strategy
-     */
-    public DuplicateResponseHeaderStrategy getStrategy() {
-        return strategy;
-    }
-    
-    /**
-     * Sets duplicate response headers handle strategy.
-     *
-     * @param strategy strategy
-     */
-    public void setStrategy(final DuplicateResponseHeaderStrategy strategy) {
-        this.strategy = strategy;
-    }
-    
-    /**
-     * Gets duplicate response headers handle strategy.
-     */
-    public enum DuplicateResponseHeaderStrategy {
-        
-        /**
-         * Default: Retain the first value only.
-         */
-        RETAIN_FIRST,
-        
-        /**
-         * Retain the last value only.
-         */
-        RETAIN_LAST,
-        
-        /**
-         * Retain all unique values in the order of their first encounter.
-         */
-        RETAIN_UNIQUE
-    }
-}
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPluginTest.java
index 77b7386f7e..aeac9d5318 100644
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPluginTest.java
@@ -26,7 +26,6 @@ import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.result.ShenyuResult;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -69,7 +68,7 @@ public final class NettyHttpClientPluginTest {
         chain = mock(ShenyuPluginChain.class);
         when(chain.execute(any())).thenReturn(Mono.empty());
         HttpClient httpClient = HttpClient.create();
-        nettyHttpClientPlugin = new NettyHttpClientPlugin(httpClient, new 
DuplicateResponseHeaderProperties());
+        nettyHttpClientPlugin = new NettyHttpClientPlugin(httpClient);
     }
 
     /**
diff --git 
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
index 204c43d554..2b26962a8a 100644
--- 
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
@@ -24,7 +24,6 @@ import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.result.ShenyuResult;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -78,7 +77,7 @@ public final class WebClientPluginTest {
         
when(context.getBean(ShenyuResult.class)).thenReturn(mock(ShenyuResult.class));
 
         WebClient webClient = mockWebClientOK();
-        webClientPlugin = new WebClientPlugin(webClient, new 
DuplicateResponseHeaderProperties());
+        webClientPlugin = new WebClientPlugin(webClient);
     }
 
     /**
@@ -91,7 +90,7 @@ public final class WebClientPluginTest {
         ServerWebExchange exchangeNoPathTest = MockServerWebExchange
                 .from(MockServerHttpRequest.get("/test").build());
         exchangeNoPathTest.getAttributes().put(Constants.CONTEXT, 
mock(ShenyuContext.class));
-        WebClientPlugin webClientPluginNoPathTest = new 
WebClientPlugin(webClientNoPathTest, new DuplicateResponseHeaderProperties());
+        WebClientPlugin webClientPluginNoPathTest = new 
WebClientPlugin(webClientNoPathTest);
         Mono<Void> monoNoPathTest = 
webClientPluginNoPathTest.execute(exchangeNoPathTest, chainNoPathTest);
         
StepVerifier.create(monoNoPathTest).expectSubscription().verifyComplete();
 
@@ -101,19 +100,19 @@ public final class WebClientPluginTest {
                 .from(MockServerHttpRequest.post("/test123?param=1").build());
         exchangePostTest.getAttributes().put(Constants.CONTEXT, 
mock(ShenyuContext.class));
         exchangePostTest.getAttributes().put(Constants.HTTP_URI, 
URI.create("/test123?param=1"));
-        WebClientPlugin webClientPluginPostTest = new 
WebClientPlugin(webClientPostTest, new DuplicateResponseHeaderProperties());
+        WebClientPlugin webClientPluginPostTest = new 
WebClientPlugin(webClientPostTest);
         Mono<Void> monoPostTest = 
webClientPluginPostTest.execute(exchangePostTest, chainPostTest);
         StepVerifier.create(monoPostTest).expectSubscription().verifyError();
 
         final ShenyuPluginChain chainOkTest = mock(ShenyuPluginChain.class);
         final WebClient webClientOkTest = mockWebClientOK();
-        WebClientPlugin webClientPluginOkTest = new 
WebClientPlugin(webClientOkTest, new DuplicateResponseHeaderProperties());
+        WebClientPlugin webClientPluginOkTest = new 
WebClientPlugin(webClientOkTest);
         Mono<Void> monoOkTest = 
webClientPluginOkTest.execute(generateServerWebExchange(), chainOkTest);
         StepVerifier.create(monoOkTest).expectSubscription().verifyError();
 
         final ShenyuPluginChain chainErrorTest = mock(ShenyuPluginChain.class);
         final WebClient webClientErrorTest = mockWebClientError();
-        WebClientPlugin webClientPluginErrorTest = new 
WebClientPlugin(webClientErrorTest, new DuplicateResponseHeaderProperties());
+        WebClientPlugin webClientPluginErrorTest = new 
WebClientPlugin(webClientErrorTest);
         Mono<Void> monoErrorTest = 
webClientPluginErrorTest.execute(generateServerWebExchange(), chainErrorTest);
         StepVerifier.create(monoErrorTest).expectSubscription().verifyError();
     }
diff --git 
a/shenyu-plugin/shenyu-plugin-request/src/main/java/org/apache/shenyu/plugin/request/RequestPlugin.java
 
b/shenyu-plugin/shenyu-plugin-request/src/main/java/org/apache/shenyu/plugin/request/RequestPlugin.java
index bc30d525cd..0d3cef6a5e 100644
--- 
a/shenyu-plugin/shenyu-plugin-request/src/main/java/org/apache/shenyu/plugin/request/RequestPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-request/src/main/java/org/apache/shenyu/plugin/request/RequestPlugin.java
@@ -20,10 +20,12 @@ package org.apache.shenyu.plugin.request;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.rule.RequestHandle;
 import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.enums.UniqueHeaderEnum;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
 import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
@@ -56,10 +58,23 @@ public class RequestPlugin extends AbstractShenyuPlugin {
     protected Mono<Void> doExecute(final ServerWebExchange exchange, final 
ShenyuPluginChain chain, final SelectorData selector,
             final RuleData rule) {
         RequestHandle requestHandle = 
RequestPluginHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(rule));
-        if (Objects.isNull(requestHandle) || requestHandle.isEmptyConfig()) {
+        if (Objects.isNull(requestHandle)) {
             LOG.error("request handler can not configuration:{}", 
requestHandle);
             return chain.execute(exchange);
         }
+        exchange.getAttributes().put(Constants.PRESERVE_HOST, 
requestHandle.getPreserveHost());
+        if (Objects.nonNull(requestHandle.getRequestHeaderUniqueStrategy()) && 
StringUtils.isNotEmpty(requestHandle.getRequestUniqueHeaders())) {
+            
exchange.getAttributes().put(UniqueHeaderEnum.REQ_UNIQUE_HEADER.getStrategy(), 
requestHandle.getRequestHeaderUniqueStrategy());
+            
exchange.getAttributes().put(UniqueHeaderEnum.REQ_UNIQUE_HEADER.getName(), 
requestHandle.getRequestUniqueHeaders());
+        }
+        if (Objects.nonNull(requestHandle.getRequestHeaderUniqueStrategy()) && 
StringUtils.isNotEmpty(requestHandle.getRespUniqueHeaders())) {
+            
exchange.getAttributes().put(UniqueHeaderEnum.RESP_UNIQUE_HEADER.getStrategy(), 
requestHandle.getRespHeaderUniqueStrategy());
+            
exchange.getAttributes().put(UniqueHeaderEnum.RESP_UNIQUE_HEADER.getName(), 
requestHandle.getRespUniqueHeaders());
+        }
+        if (requestHandle.isEmptyConfig()) {
+            LOG.warn("request handler configuration is empty:{}", 
requestHandle);
+            return chain.execute(exchange);
+        }
         ServerHttpRequest request = exchange.getRequest();
         ServerWebExchange modifiedExchange = exchange.mutate()
                 .request(originalRequest -> originalRequest.uri(
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-httpclient/src/main/java/org/apache/shenyu/springboot/starter/plugin/httpclient/HttpClientPluginConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-httpclient/src/main/java/org/apache/shenyu/springboot/starter/plugin/httpclient/HttpClientPluginConfiguration.java
index c889a90e3a..cbd6b83765 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-httpclient/src/main/java/org/apache/shenyu/springboot/starter/plugin/httpclient/HttpClientPluginConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-httpclient/src/main/java/org/apache/shenyu/springboot/starter/plugin/httpclient/HttpClientPluginConfiguration.java
@@ -21,7 +21,6 @@ import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
 import org.apache.shenyu.plugin.httpclient.NettyHttpClientPlugin;
 import org.apache.shenyu.plugin.httpclient.WebClientPlugin;
-import 
org.apache.shenyu.plugin.httpclient.config.DuplicateResponseHeaderProperties;
 import org.apache.shenyu.plugin.httpclient.config.HttpClientProperties;
 import org.springframework.beans.factory.ObjectProvider;
 import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -54,17 +53,6 @@ public class HttpClientPluginConfiguration {
     public HttpClientProperties httpClientProperties() {
         return new HttpClientProperties();
     }
-    
-    /**
-     * http response duplicate response headers config.
-     *
-     * @return the duplicate response header properties
-     */
-    @Bean
-    @ConfigurationProperties(prefix = "shenyu.duplicate-response-header")
-    public DuplicateResponseHeaderProperties responseHeaderProperties() {
-        return new DuplicateResponseHeaderProperties();
-    }
 
     /**
      * Http client loop resource.
@@ -113,8 +101,7 @@ public class HttpClientPluginConfiguration {
         @Bean
         public ShenyuPlugin webClientPlugin(
                 final HttpClientProperties properties,
-                final ObjectProvider<HttpClient> httpClient,
-                final DuplicateResponseHeaderProperties 
responseHeaderProperties) {
+                final ObjectProvider<HttpClient> httpClient) {
             WebClient webClient = WebClient.builder()
                     // fix Exceeded limit on max bytes to buffer
                     // detail see 
https://stackoverflow.com/questions/59326351/configure-spring-codec-max-in-memory-size-when-using-reactiveelasticsearchclient
@@ -123,7 +110,7 @@ public class HttpClientPluginConfiguration {
                             .build())
                     .clientConnector(new 
ReactorClientHttpConnector(Objects.requireNonNull(httpClient.getIfAvailable())))
                     .build();
-            return new WebClientPlugin(webClient, responseHeaderProperties);
+            return new WebClientPlugin(webClient);
         }
     }
 
@@ -141,9 +128,8 @@ public class HttpClientPluginConfiguration {
          * @return the shenyu plugin
          */
         @Bean
-        public ShenyuPlugin nettyHttpClientPlugin(final 
ObjectProvider<HttpClient> httpClient,
-                                                  final 
DuplicateResponseHeaderProperties responseHeaderProperties) {
-            return new NettyHttpClientPlugin(httpClient.getIfAvailable(), 
responseHeaderProperties);
+        public ShenyuPlugin nettyHttpClientPlugin(final 
ObjectProvider<HttpClient> httpClient) {
+            return new NettyHttpClientPlugin(httpClient.getIfAvailable());
         }
     }
 }

Reply via email to