feat: basic support Apache APISIX 2.13.0 (#2428)

diff --git a/api/conf/schema.json b/api/conf/schema.json
index a65c22a..fd88252 100644
--- a/api/conf/schema.json
+++ b/api/conf/schema.json
@@ -11,7 +11,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -97,7 +96,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -378,7 +376,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -931,7 +928,6 @@
 						},
 						"labels": {
 							"description": "key/value pairs to specify attributes",
-							"maxProperties": 16,
 							"patternProperties": {
 								".*": {
 									"description": "value of label",
@@ -1161,7 +1157,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -1555,7 +1550,6 @@
 						},
 						"labels": {
 							"description": "key/value pairs to specify attributes",
-							"maxProperties": 16,
 							"patternProperties": {
 								".*": {
 									"description": "value of label",
@@ -1815,7 +1809,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -2316,7 +2309,6 @@
 						},
 						"labels": {
 							"description": "key/value pairs to specify attributes",
-							"maxProperties": 16,
 							"patternProperties": {
 								".*": {
 									"description": "value of label",
@@ -2857,7 +2849,6 @@
 				},
 				"labels": {
 					"description": "key/value pairs to specify attributes",
-					"maxProperties": 16,
 					"patternProperties": {
 						".*": {
 							"description": "value of label",
@@ -3237,6 +3228,21 @@
 					}
 				],
 				"properties": {
+					"access_denied_redirect_uri": {
+						"maxLength": 2048,
+						"minLength": 1,
+						"type": "string"
+					},
+					"access_token_expires_in": {
+						"default": 300,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"access_token_expires_leeway": {
+						"default": 0,
+						"minimum": 0,
+						"type": "integer"
+					},
 					"audience": {
 						"description": "Deprecated, use `client_id` instead.",
 						"maxLength": 100,
@@ -3315,6 +3321,16 @@
 						],
 						"type": "string"
 					},
+					"refresh_token_expires_in": {
+						"default": 3600,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"refresh_token_expires_leeway": {
+						"default": 0,
+						"minimum": 0,
+						"type": "integer"
+					},
 					"resource_registration_endpoint": {
 						"maxLength": 4096,
 						"minLength": 1,
@@ -3542,6 +3558,97 @@
 			"scope": "global",
 			"version": 0.1
 		},
+		"clickhouse-logger": {
+			"metadata_schema": {
+				"properties": {
+					"log_format": {
+						"default": {
+							"@timestamp": "$time_iso8601",
+							"client_ip": "$remote_addr",
+							"host": "$host"
+						},
+						"type": "object"
+					}
+				},
+				"type": "object"
+			},
+			"priority": 398,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"batch_max_size": {
+						"default": 1000,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"buffer_duration": {
+						"default": 60,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"database": {
+						"default": "",
+						"type": "string"
+					},
+					"disable": {
+						"type": "boolean"
+					},
+					"endpoint_addr": {
+						"pattern": "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?",
+						"type": "string"
+					},
+					"inactive_timeout": {
+						"default": 5,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"logtable": {
+						"default": "",
+						"type": "string"
+					},
+					"max_retry_count": {
+						"default": 0,
+						"minimum": 0,
+						"type": "integer"
+					},
+					"name": {
+						"default": "clickhouse-logger",
+						"type": "string"
+					},
+					"password": {
+						"default": "",
+						"type": "string"
+					},
+					"retry_delay": {
+						"default": 1,
+						"minimum": 0,
+						"type": "integer"
+					},
+					"ssl_verify": {
+						"default": true,
+						"type": "boolean"
+					},
+					"timeout": {
+						"default": 3,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"user": {
+						"default": "",
+						"type": "string"
+					}
+				},
+				"required": [
+					"database",
+					"endpoint_addr",
+					"logtable",
+					"password",
+					"user"
+				],
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"client-control": {
 			"priority": 22000,
 			"schema": {
@@ -3651,6 +3758,18 @@
 			"version": 0.1
 		},
 		"cors": {
+			"metadata_schema": {
+				"properties": {
+					"allow_origins": {
+						"additionalProperties": {
+							"pattern": "^(\\*|\\*\\*|null|\\w+://[^,]+(,\\w+://[^,]+)*)$",
+							"type": "string"
+						},
+						"type": "object"
+					}
+				},
+				"type": "object"
+			},
 			"priority": 4000,
 			"schema": {
 				"$comment": "this is a mark for our injected plugin schema",
@@ -3676,6 +3795,17 @@
 						"pattern": "^(\\*|\\*\\*|null|\\w+://[^,]+(,\\w+://[^,]+)*)$",
 						"type": "string"
 					},
+					"allow_origins_by_metadata": {
+						"description": "set allowed origins by referencing origins in plugin metadata",
+						"items": {
+							"maxLength": 4096,
+							"minLength": 1,
+							"type": "string"
+						},
+						"minItems": 1,
+						"type": "array",
+						"uniqueItems": true
+					},
 					"allow_origins_by_regex": {
 						"description": "you can use regex to allow specific origins when no credentials,for example use [.*\\.test.com] to allow a.test.com and b.test.com",
 						"items": {
@@ -3705,6 +3835,36 @@
 			},
 			"version": 0.1
 		},
+		"csrf": {
+			"priority": 2980,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"disable": {
+						"type": "boolean"
+					},
+					"expires": {
+						"default": 7200,
+						"description": "expires time(s) for csrf token",
+						"type": "integer"
+					},
+					"key": {
+						"description": "use to generate csrf token",
+						"type": "string"
+					},
+					"name": {
+						"default": "apisix-csrf-token",
+						"description": "the csrf token name",
+						"type": "string"
+					}
+				},
+				"required": [
+					"key"
+				],
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"datadog": {
 			"metadata_schema": {
 				"properties": {
@@ -3870,6 +4030,11 @@
 					},
 					{
 						"required": [
+							"clickhouse"
+						]
+					},
+					{
+						"required": [
 							"host",
 							"port"
 						]
@@ -3886,6 +4051,41 @@
 						"minimum": 1,
 						"type": "integer"
 					},
+					"clickhouse": {
+						"properties": {
+							"database": {
+								"default": "",
+								"type": "string"
+							},
+							"endpoint_addr": {
+								"1": {
+									"pattern": "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?",
+									"type": "string"
+								},
+								"default": "http://127.0.0.1:8123"
+							},
+							"logtable": {
+								"default": "",
+								"type": "string"
+							},
+							"password": {
+								"default": "",
+								"type": "string"
+							},
+							"user": {
+								"default": "default",
+								"type": "string"
+							}
+						},
+						"required": [
+							"database",
+							"endpoint_addr",
+							"logtable",
+							"password",
+							"user"
+						],
+						"type": "object"
+					},
 					"host": {
 						"1": {
 							"pattern": "^\\*?[0-9a-zA-Z-._]+$",
@@ -4199,6 +4399,38 @@
 			},
 			"version": 0.1
 		},
+		"file-logger": {
+			"metadata_schema": {
+				"properties": {
+					"log_format": {
+						"default": {
+							"@timestamp": "$time_iso8601",
+							"client_ip": "$remote_addr",
+							"host": "$host"
+						},
+						"type": "object"
+					}
+				},
+				"type": "object"
+			},
+			"priority": 399,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"disable": {
+						"type": "boolean"
+					},
+					"path": {
+						"type": "string"
+					}
+				},
+				"required": [
+					"path"
+				],
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"forward-auth": {
 			"priority": 2002,
 			"schema": {
@@ -4717,6 +4949,10 @@
 						"minimum": 0,
 						"type": "integer"
 					},
+					"ssl_verify": {
+						"default": false,
+						"type": "boolean"
+					},
 					"timeout": {
 						"default": 3,
 						"minimum": 1,
@@ -4914,8 +5150,20 @@
 			"schema": {
 				"$comment": "this is a mark for our injected plugin schema",
 				"properties": {
+					"cookie": {
+						"default": "jwt",
+						"type": "string"
+					},
 					"disable": {
 						"type": "boolean"
+					},
+					"header": {
+						"default": "authorization",
+						"type": "string"
+					},
+					"query": {
+						"default": "jwt",
+						"type": "string"
 					}
 				},
 				"type": "object"
@@ -5197,90 +5445,55 @@
 			"priority": 1002,
 			"schema": {
 				"$comment": "this is a mark for our injected plugin schema",
-				"dependencies": {
-					"policy": {
-						"oneOf": [
-							{
-								"properties": {
-									"policy": {
-										"enum": [
-											"local"
-										]
-									}
-								}
-							},
-							{
-								"properties": {
-									"policy": {
-										"enum": [
-											"redis"
-										]
-									},
-									"redis_database": {
-										"default": 0,
-										"minimum": 0,
-										"type": "integer"
-									},
-									"redis_host": {
-										"minLength": 2,
-										"type": "string"
-									},
-									"redis_password": {
-										"minLength": 0,
-										"type": "string"
-									},
-									"redis_port": {
-										"default": 6379,
-										"minimum": 1,
-										"type": "integer"
-									},
-									"redis_timeout": {
-										"default": 1000,
-										"minimum": 1,
-										"type": "integer"
-									}
-								},
-								"required": [
-									"redis_host"
-								]
-							},
-							{
-								"properties": {
-									"policy": {
-										"enum": [
-											"redis-cluster"
-										]
-									},
-									"redis_cluster_name": {
-										"type": "string"
-									},
-									"redis_cluster_nodes": {
-										"items": {
-											"maxLength": 100,
-											"minLength": 2,
-											"type": "string"
-										},
-										"minItems": 2,
-										"type": "array"
-									},
-									"redis_password": {
-										"minLength": 0,
-										"type": "string"
-									},
-									"redis_timeout": {
-										"default": 1000,
-										"minimum": 1,
-										"type": "integer"
-									}
-								},
-								"required": [
-									"redis_cluster_name",
-									"redis_cluster_nodes"
+				"else": {
+					"if": {
+						"properties": {
+							"policy": {
+								"enum": [
+									"redis-cluster"
 								]
 							}
+						}
+					},
+					"then": {
+						"properties": {
+							"redis_cluster_name": {
+								"type": "string"
+							},
+							"redis_cluster_nodes": {
+								"items": {
+									"maxLength": 100,
+									"minLength": 2,
+									"type": "string"
+								},
+								"minItems": 2,
+								"type": "array"
+							},
+							"redis_password": {
+								"minLength": 0,
+								"type": "string"
+							},
+							"redis_timeout": {
+								"default": 1000,
+								"minimum": 1,
+								"type": "integer"
+							}
+						},
+						"required": [
+							"redis_cluster_name",
+							"redis_cluster_nodes"
 						]
 					}
 				},
+				"if": {
+					"properties": {
+						"policy": {
+							"enum": [
+								"redis"
+							]
+						}
+					}
+				},
 				"properties": {
 					"allow_degradation": {
 						"default": false,
@@ -5341,6 +5554,36 @@
 					"count",
 					"time_window"
 				],
+				"then": {
+					"properties": {
+						"redis_database": {
+							"default": 0,
+							"minimum": 0,
+							"type": "integer"
+						},
+						"redis_host": {
+							"minLength": 2,
+							"type": "string"
+						},
+						"redis_password": {
+							"minLength": 0,
+							"type": "string"
+						},
+						"redis_port": {
+							"default": 6379,
+							"minimum": 1,
+							"type": "integer"
+						},
+						"redis_timeout": {
+							"default": 1000,
+							"minimum": 1,
+							"type": "integer"
+						}
+					},
+					"required": [
+						"redis_host"
+					]
+				},
 				"type": "object"
 			},
 			"version": 0.4
@@ -5414,6 +5657,214 @@
 			"scope": "global",
 			"version": 0.1
 		},
+		"loggly": {
+			"metadata_schema": {
+				"properties": {
+					"host": {
+						"default": "logs-01.loggly.com",
+						"type": "string"
+					},
+					"log_format": {
+						"type": "object"
+					},
+					"port": {
+						"default": 514,
+						"type": "integer"
+					},
+					"protocol": {
+						"default": "syslog",
+						"enum": [
+							"http",
+							"https",
+							"syslog"
+						],
+						"type": "string"
+					},
+					"timeout": {
+						"default": 5000,
+						"minimum": 1,
+						"type": "integer"
+					}
+				},
+				"type": "object"
+			},
+			"priority": 411,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"batch_max_size": {
+						"default": 1000,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"buffer_duration": {
+						"default": 60,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"customer_token": {
+						"type": "string"
+					},
+					"disable": {
+						"type": "boolean"
+					},
+					"inactive_timeout": {
+						"default": 5,
+						"minimum": 1,
+						"type": "integer"
+					},
+					"include_req_body": {
+						"default": false,
+						"type": "boolean"
+					},
+					"include_resp_body": {
+						"default": false,
+						"type": "boolean"
+					},
+					"include_resp_body_expr": {
+						"items": {
+							"type": "array"
+						},
+						"minItems": 1,
+						"type": "array"
+					},
+					"max_retry_count": {
+						"default": 0,
+						"minimum": 0,
+						"type": "integer"
+					},
+					"name": {
+						"default": "loggly",
+						"type": "string"
+					},
+					"retry_delay": {
+						"default": 1,
+						"minimum": 0,
+						"type": "integer"
+					},
+					"severity": {
+						"default": "INFO",
+						"description": "base severity log level",
+						"enum": [
+							"ALERT",
+							"CRIT",
+							"DEBUG",
+							"EMEGR",
+							"ERR",
+							"INFO",
+							"NOTICE",
+							"WARNING",
+							"alert",
+							"crit",
+							"debug",
+							"emegr",
+							"err",
+							"info",
+							"notice",
+							"warning"
+						],
+						"type": "string"
+					},
+					"severity_map": {
+						"additionalProperties": false,
+						"description": "upstream response code vs syslog severity mapping",
+						"patternProperties": {
+							"^[1-5][0-9]{2}$": {
+								"description": "keys are HTTP status code, values are severity",
+								"enum": [
+									"ALERT",
+									"CRIT",
+									"DEBUG",
+									"EMEGR",
+									"ERR",
+									"INFO",
+									"NOTICE",
+									"WARNING",
+									"alert",
+									"crit",
+									"debug",
+									"emegr",
+									"err",
+									"info",
+									"notice",
+									"warning"
+								],
+								"type": "string"
+							}
+						},
+						"type": "object"
+					},
+					"ssl_verify": {
+						"default": true,
+						"type": "boolean"
+					},
+					"tags": {
+						"default": [
+							"apisix"
+						],
+						"items": {
+							"pattern": "^(?!tag=)[ -~]*",
+							"type": "string"
+						},
+						"minItems": 1,
+						"type": "array"
+					}
+				},
+				"required": [
+					"customer_token"
+				],
+				"type": "object"
+			},
+			"version": 0.1
+		},
+		"mocking": {
+			"priority": 10900,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"anyOf": [
+					{
+						"required": [
+							"response_example"
+						]
+					},
+					{
+						"required": [
+							"response_schema"
+						]
+					}
+				],
+				"properties": {
+					"content_type": {
+						"default": "application/json;charset=utf8",
+						"type": "string"
+					},
+					"delay": {
+						"default": 0,
+						"type": "integer"
+					},
+					"disable": {
+						"type": "boolean"
+					},
+					"response_example": {
+						"type": "string"
+					},
+					"response_schema": {
+						"type": "object"
+					},
+					"response_status": {
+						"default": 200,
+						"minimum": 100,
+						"type": "integer"
+					},
+					"with_mock_header": {
+						"default": true,
+						"type": "boolean"
+					}
+				},
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"node-status": {
 			"priority": 1000,
 			"schema": {
@@ -5525,6 +5976,10 @@
 						"default": "/logout",
 						"type": "string"
 					},
+					"post_logout_redirect_uri": {
+						"description": "the URI will be redirect when request logout_path",
+						"type": "string"
+					},
 					"public_key": {
 						"type": "string"
 					},
@@ -5578,6 +6033,102 @@
 			},
 			"version": 0.1
 		},
+		"opentelemetry": {
+			"priority": 12009,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"additional_attributes": {
+						"items": {
+							"minLength": 1,
+							"type": "string"
+						},
+						"type": "array"
+					},
+					"disable": {
+						"type": "boolean"
+					},
+					"sampler": {
+						"default": {
+							"name": "always_off",
+							"options": {
+								"fraction": 0,
+								"root": {
+									"name": "always_off"
+								}
+							}
+						},
+						"properties": {
+							"name": {
+								"default": "always_off",
+								"enum": [
+									"always_off",
+									"always_on",
+									"parent_base",
+									"trace_id_ratio"
+								],
+								"title": "sampling strategy",
+								"type": "string"
+							},
+							"options": {
+								"default": {
+									"fraction": 0,
+									"root": {
+										"name": "always_off"
+									}
+								},
+								"properties": {
+									"fraction": {
+										"default": 0,
+										"title": "trace_id_ratio fraction",
+										"type": "number"
+									},
+									"root": {
+										"default": {
+											"name": "always_off",
+											"options": {
+												"fraction": 0
+											}
+										},
+										"properties": {
+											"name": {
+												"default": "always_off",
+												"enum": [
+													"always_off",
+													"always_on",
+													"trace_id_ratio"
+												],
+												"title": "sampling strategy",
+												"type": "string"
+											},
+											"options": {
+												"default": {
+													"fraction": 0
+												},
+												"properties": {
+													"fraction": {
+														"default": 0,
+														"title": "trace_id_ratio fraction parameter",
+														"type": "number"
+													}
+												},
+												"type": "object"
+											}
+										},
+										"title": "parent_base root sampler",
+										"type": "object"
+									}
+								},
+								"type": "object"
+							}
+						},
+						"type": "object"
+					}
+				},
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"openwhisk": {
 			"priority": -1901,
 			"schema": {
@@ -5793,7 +6344,11 @@
 						"type": "boolean"
 					},
 					"host": {
-						"pattern": "^http(s)?:\\/\\/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:[0-9]{1,5})?$",
+						"pattern": "^http(s)?:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?$",
+						"type": "string"
+					},
+					"path": {
+						"pattern": "^/[^?&]+$",
 						"type": "string"
 					},
 					"sample_ratio": {
@@ -5879,6 +6434,22 @@
 			},
 			"version": 0.1
 		},
+		"public-api": {
+			"priority": 501,
+			"schema": {
+				"$comment": "this is a mark for our injected plugin schema",
+				"properties": {
+					"disable": {
+						"type": "boolean"
+					},
+					"uri": {
+						"type": "string"
+					}
+				},
+				"type": "object"
+			},
+			"version": 0.1
+		},
 		"real-ip": {
 			"priority": 23000,
 			"schema": {
@@ -6355,7 +6926,7 @@
 			"version": 0.1
 		},
 		"skywalking": {
-			"priority": -1100,
+			"priority": 12010,
 			"schema": {
 				"$comment": "this is a mark for our injected plugin schema",
 				"properties": {
@@ -6647,7 +7218,6 @@
 						"type": "integer"
 					},
 					"max_retry_times": {
-						"default": 1,
 						"minimum": 1,
 						"type": "integer"
 					},
@@ -6669,7 +7239,6 @@
 						"type": "integer"
 					},
 					"retry_interval": {
-						"default": 1,
 						"minimum": 0,
 						"type": "integer"
 					},
@@ -7164,7 +7733,6 @@
 													},
 													"labels": {
 														"description": "key/value pairs to specify attributes",
-														"maxProperties": 16,
 														"patternProperties": {
 															".*": {
 																"description": "value of label",
@@ -7525,7 +8093,7 @@
 			"version": 0.1
 		},
 		"zipkin": {
-			"priority": 11011,
+			"priority": 12011,
 			"schema": {
 				"$comment": "this is a mark for our injected plugin schema",
 				"properties": {
diff --git a/api/internal/core/store/validate_test.go b/api/internal/core/store/validate_test.go
index c85e39a..6ea2466 100644
--- a/api/internal/core/store/validate_test.go
+++ b/api/internal/core/store/validate_test.go
@@ -82,8 +82,9 @@
 		      "count": 2,
 		      "time_window": 60,
 		      "rejected_code": 503,
-		      "key": "remote_addr"
-		  }
+		      "key": "remote_addr",
+			  "policy": "local"
+		  	}
 		},
 		"desc": "test description"
 	}`
@@ -105,7 +106,8 @@
 			"limit-count": {
 				"time_window": 60,
 				"rejected_code": 503,
-				"key": "remote_addr"
+				"key": "remote_addr",
+				"policy": "local"
 			}
 		},
 		"desc": "test description"
diff --git a/api/test/e2enew/consumer/consumer_test.go b/api/test/e2enew/consumer/consumer_test.go
index d420f88..0b25bcc 100644
--- a/api/test/e2enew/consumer/consumer_test.go
+++ b/api/test/e2enew/consumer/consumer_test.go
@@ -41,7 +41,8 @@
 						"count": 2,
 						"time_window": 60,
 						"rejected_code": 503,
-						"key": "remote_addr"
+						"key": "remote_addr",
+						"policy": "local"
 					}
 				},
 				"desc": "test description"
@@ -69,7 +70,8 @@
 						"count": 2,
 						"time_window": 60,
 						"rejected_code": 504,
-						"key": "remote_addr"
+						"key": "remote_addr",
+						"policy": "local"
 					}
 				},
 				"desc": "test description"
@@ -111,7 +113,8 @@
 					"count": 2,
 					"time_window": 60,
 					"rejected_code": 503,
-					"key": "remote_addr"
+					"key": "remote_addr",
+					"policy": "local"
 					}
 				},
 				"desc": "test description"
diff --git a/api/test/e2enew/label/label_test.go b/api/test/e2enew/label/label_test.go
index 12f5900..954f72d 100644
--- a/api/test/e2enew/label/label_test.go
+++ b/api/test/e2enew/label/label_test.go
@@ -109,7 +109,8 @@
 							 "count": 2,
 							 "time_window": 60,
 							 "rejected_code": 503,
-							 "key": "remote_addr"
+							 "key": "remote_addr",
+							 "policy": "local"
 						 }
 					 },
 					 "upstream": {
diff --git a/api/test/e2enew/route/route_export_test.go b/api/test/e2enew/route/route_export_test.go
index 7e245df..de9923c 100644
--- a/api/test/e2enew/route/route_export_test.go
+++ b/api/test/e2enew/route/route_export_test.go
@@ -66,6 +66,7 @@
 						"limit-count": {
 							"count": 2,
 							"key": "remote_addr",
+							"policy": "local",
 							"rejected_code": 503,
 							"time_window": 60
 						}
@@ -100,6 +101,7 @@
 						"limit-count": {
 							"count": 2,
 							"key": "remote_addr",
+							"policy": "local",
 							"rejected_code": 503,
 							"time_window": 60
 						}
@@ -142,7 +144,8 @@
 							"count": 2,
 							"time_window": 60,
 							"rejected_code": 503,
-							"key": "remote_addr"
+							"key": "remote_addr",
+							"policy": "local"
 						}
 					},
 					"status": 1,
@@ -195,6 +198,7 @@
 						"limit-count": {
 							"count": 2,
 							"key": "remote_addr",
+							"policy": "local",
 							"rejected_code": 503,
 							"time_window": 60
 						}
@@ -229,6 +233,7 @@
 						"limit-count": {
 							"count": 2,
 							"key": "remote_addr",
+							"policy": "local",
 							"rejected_code": 503,
 							"time_window": 60
 						}
@@ -272,7 +277,8 @@
 							"count": 2,
 							"time_window": 60,
 							"rejected_code": 503,
-							"key": "remote_addr"
+							"key": "remote_addr",
+							"policy": "local"
 						}
 					},
 					"status": 1,
@@ -376,6 +382,7 @@
 				"limit-count": {
 					"count": 100,
 					"key": "remote_addr",
+					"policy": "local",
 					"rejected_code": 503,
 					"time_window": 60
 				}
@@ -417,6 +424,7 @@
 							"limit-count": {
 								"count": 100,
 								"key": "remote_addr",
+								"policy": "local",
 								"rejected_code": 503,
 								"time_window": 60
 							}
@@ -455,6 +463,7 @@
 						 "limit-count": {
 							 "count": 100,
 							 "time_window": 60,
+							 "policy": "local",
 							 "rejected_code": 503,
 							 "key": "remote_addr"
 						 }
@@ -557,6 +566,7 @@
 				"limit-count": {
 					"count": 100,
 					"key": "remote_addr",
+					"policy": "local",
 					"rejected_code": 503,
 					"time_window": 60
 				}
@@ -598,6 +608,7 @@
 							"limit-count": {
 								"count": 100,
 								"key": "remote_addr",
+								"policy": "local",
 								"rejected_code": 503,
 								"time_window": 60
 							},
@@ -640,7 +651,8 @@
 							"count": 100,
 							"time_window": 60,
 							"rejected_code": 503,
-							"key": "remote_addr"
+							"key": "remote_addr",
+							"policy": "local"
 						}
 					},
 					"upstream": {
@@ -746,6 +758,7 @@
 				"limit-count": {
 					"count": 100,
 					"key": "remote_addr",
+					"policy": "local",
 					"rejected_code": 503,
 					"time_window": 60
 				}
@@ -787,6 +800,7 @@
 							"limit-count": {
 								"count": 100,
 								"key": "remote_addr",
+								"policy": "local",
 								"rejected_code": 503,
 								"time_window": 60
 							},
@@ -847,7 +861,8 @@
 							"count": 100,
 							"time_window": 60,
 							"rejected_code": 503,
-							"key": "remote_addr"
+							"key": "remote_addr",
+							"policy": "local"
 						}
 					},
 					"upstream_id": "1"
diff --git a/api/test/e2enew/route/route_with_plugin_limit_count_test.go b/api/test/e2enew/route/route_with_plugin_limit_count_test.go
index 45e384b..a25d15c 100644
--- a/api/test/e2enew/route/route_with_plugin_limit_count_test.go
+++ b/api/test/e2enew/route/route_with_plugin_limit_count_test.go
@@ -50,7 +50,8 @@
 						"count": 2,
 						"time_window": 2,
 						"rejected_code": 503,
-						"key": "remote_addr"
+						"key": "remote_addr",
+						"policy": "local"
 					}
 				},
 				"upstream": {
@@ -137,7 +138,8 @@
 					   "count": 2,
 					   "time_window": 2,
 					   "rejected_code": 503,
-					   "key": "consumer_name"
+					   "key": "consumer_name",
+					   "policy": "local"
 				   }
 			   },
 			   "upstream": {
@@ -305,7 +307,8 @@
 					   "time_window": 2,
 					   "rejected_code": 503,
 					   "key": "remote_addr",
-					   "disable": false
+					   "disable": false,
+					   "policy": "local"
 				   }
 			   },
 			   "upstream": {
@@ -362,7 +365,8 @@
 					   "time_window": 2,
 					   "rejected_code": 503,
 					   "key": "remote_addr",
-					   "disable": true
+					   "disable": true,
+					   "policy": "local"
 				   }
 			   },
 			   "upstream": {
diff --git a/api/test/e2enew/schema/schema_test.go b/api/test/e2enew/schema/schema_test.go
index fb99b27..05127f4 100644
--- a/api/test/e2enew/schema/schema_test.go
+++ b/api/test/e2enew/schema/schema_test.go
@@ -45,7 +45,7 @@
 			Path:         "/apisix/admin/schema/plugins/jwt-auth",
 			Headers:      map[string]string{"Authorization": base.GetToken()},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   "{\"$comment\":\"this is a mark for our injected plugin schema\",\"properties\":{\"disable\":{\"type\":\"boolean\"}},\"type\":\"object\"}",
+			ExpectBody:   `{"$comment":"this is a mark for our injected plugin schema","properties":{"cookie":{"default":"jwt","type":"string"},"disable":{"type":"boolean"},"header":{"default":"authorization","type":"string"},"query":{"default":"jwt","type":"string"}}`,
 			Sleep:        base.SleepTime,
 		}),
 		table.Entry("get schema of non-existent plugin", base.HttpTestCase{
@@ -63,7 +63,7 @@
 			Path:         "/apisix/admin/schemas/consumer",
 			Headers:      map[string]string{"Authorization": base.GetToken()},
 			ExpectStatus: http.StatusOK,
-			ExpectBody:   `"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"labels":{"description":"key/value pairs to specify attributes","maxProperties":16,"patternProperties":{".*":{"description":"value of label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_time":{"type":"integer"},"username":{"maxLength":100,"minLength":1,"pattern":"^[a-zA-Z0-9_]+$","type":"string"}}`,
+			ExpectBody:   `"properties":{"create_time":{"type":"integer"},"desc":{"maxLength":256,"type":"string"},"labels":{"description":"key/value pairs to specify attributes","patternProperties":{".*":{"description":"value of label","maxLength":64,"minLength":1,"pattern":"^\\S+$","type":"string"}},"type":"object"},"plugins":{"type":"object"},"update_time":{"type":"integer"},"username":{"maxLength":100,"minLength":1,"pattern":"^[a-zA-Z0-9_]+$","type":"string"}}`,
 			Sleep:        base.SleepTime,
 		}),
 		table.Entry("get schema of non-existent resources", base.HttpTestCase{
diff --git a/api/test/e2enew/service/service_test.go b/api/test/e2enew/service/service_test.go
index fde787b..39643d9 100644
--- a/api/test/e2enew/service/service_test.go
+++ b/api/test/e2enew/service/service_test.go
@@ -193,6 +193,7 @@
 					"time_window":   60,
 					"rejected_code": 503,
 					"key":           "remote_addr",
+					"policy":        "local",
 				},
 			},
 			"upstream": map[string]interface{}{
@@ -225,7 +226,7 @@
 			Path:       "/apisix/admin/services/s1",
 			Headers:    map[string]string{"Authorization": base.GetToken()},
 			ExpectCode: http.StatusOK,
-			ExpectBody: "\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"rejected_code\":503,\"time_window\":60}}",
+			ExpectBody: "\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"policy\":\"local\",\"rejected_code\":503,\"time_window\":60}}",
 			Sleep:      base.SleepTime,
 		})
 	})
@@ -306,6 +307,7 @@
 					"time_window":   60,
 					"rejected_code": 503,
 					"key":           "remote_addr",
+					"policy":        "local",
 				},
 			},
 			"upstream": map[string]interface{}{
@@ -341,7 +343,7 @@
 			Path:       "/apisix/admin/services/s2",
 			Headers:    map[string]string{"Authorization": base.GetToken()},
 			ExpectCode: http.StatusOK,
-			ExpectBody: "\"name\":\"testservice22\",\"desc\":\"testservice_desc\",\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"rejected_code\":503,\"time_window\":60}},\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v2\"},\"enable_websocket\":true}",
+			ExpectBody: "\"name\":\"testservice22\",\"desc\":\"testservice_desc\",\"upstream\":{\"nodes\":[{\"host\":\"" + base.UpstreamIp + "\",\"port\":1980,\"weight\":1}],\"type\":\"roundrobin\"},\"plugins\":{\"limit-count\":{\"count\":100,\"key\":\"remote_addr\",\"policy\":\"local\",\"rejected_code\":503,\"time_window\":60}},\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v2\"},\"enable_websocket\":true}",
 			Sleep:      base.SleepTime,
 		})
 	})
diff --git a/api/test/testdata/invalid-dag-conf.json b/api/test/testdata/invalid-dag-conf.json
index c11916a..260e06a 100644
--- a/api/test/testdata/invalid-dag-conf.json
+++ b/api/test/testdata/invalid-dag-conf.json
@@ -29,7 +29,8 @@
           "count":2,
           "time_window":60,
           "rejected_code":503,
-          "key":"remote_addr"
+          "key":"remote_addr",
+          "policy": "local"
         }
       },
       "yy-uu-ii-oo":{
diff --git a/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md b/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
index 40d1e52..bd49c14 100644
--- a/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
+++ b/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
@@ -219,6 +219,7 @@
           time_window: 60
           rejected_code: 503
           key: remote_addr
+          policy: local
       responses:
         '200':
           description: list response
diff --git a/web/cypress/fixtures/plugin-dataset.json b/web/cypress/fixtures/plugin-dataset.json
index 6f02cde..f56bb37 100644
--- a/web/cypress/fixtures/plugin-dataset.json
+++ b/web/cypress/fixtures/plugin-dataset.json
@@ -593,7 +593,13 @@
   "limit-count": [
     {
       "shouldValid": true,
-      "data": { "count": 2, "time_window": 60, "rejected_code": 503, "key": "remote_addr" }
+      "data": {
+        "count": 2,
+        "time_window": 60,
+        "rejected_code": 503,
+        "key": "remote_addr",
+        "policy": "local"
+      }
     },
     {
       "shouldValid": true,
@@ -601,14 +607,16 @@
         "count": 2,
         "time_window": 60,
         "rejected_code": 503,
-        "key": "host"
+        "key": "host",
+        "policy": "local"
       }
     },
     {
       "shouldValid": false,
       "data": {
         "time_window": 60,
-        "rejected_code": 503
+        "rejected_code": 503,
+        "policy": "local"
       }
     },
     {
@@ -617,7 +625,8 @@
         "count": -100,
         "time_window": 60,
         "rejected_code": 503,
-        "key": "remote_addr"
+        "key": "remote_addr",
+        "policy": "local"
       }
     },
     {
@@ -626,7 +635,8 @@
         "count": 2,
         "time_window": 60,
         "rejected_code": 503,
-        "key": "server_addr"
+        "key": "server_addr",
+        "policy": "local"
       }
     },
     {
@@ -634,7 +644,8 @@
       "data": {
         "count": 2,
         "time_window": 60,
-        "key": "remote_addr"
+        "key": "remote_addr",
+        "policy": "local"
       }
     }
   ],
diff --git a/web/src/components/Plugin/PluginDetail.tsx b/web/src/components/Plugin/PluginDetail.tsx
index fde1626..4170a15 100644
--- a/web/src/components/Plugin/PluginDetail.tsx
+++ b/web/src/components/Plugin/PluginDetail.tsx
@@ -129,10 +129,16 @@
 
     if (name === 'cors') {
       const newMethods = formData.allow_methods.join(',');
-      const compactAllowRegex = compact(formData.allow_origins_by_regex);
-      // Note: default allow_origins_by_regex setted for UI is [''], but this is not allowed, omit it.
-      if (compactAllowRegex.length === 0) {
-        return omit({ ...formData, allow_methods: newMethods }, ['allow_origins_by_regex']);
+      const isFilterAllowRegex = compact(formData.allow_origins_by_regex).length === 0;
+      const isFilterAllowMetadata = compact(formData.allow_origins_by_metadata).length === 0;
+      // Note: default allow_origins_by_regex and allow_origins_by_metadata setted for UI is [''], but this is not allowed, omit it.
+      if (isFilterAllowRegex || isFilterAllowMetadata) {
+        const filterAllowRegex = (isFilterAllowRegex && 'allow_origins_by_regex') || '';
+        const filterAllowMetadata = (isFilterAllowMetadata && 'allow_origins_by_metadata') || '';
+        return omit({ ...formData, allow_methods: newMethods }, [
+          filterAllowRegex,
+          filterAllowMetadata,
+        ]);
       }
 
       return { ...formData, allow_methods: newMethods };
@@ -309,7 +315,10 @@
   };
 
   const isNoConfigurationRequired =
-    pluginType === 'auth' && schemaType !== 'consumer' && monacoMode !== monacoModeList.UIForm && targetPluginName !== 'key-auth';
+    pluginType === 'auth' &&
+    schemaType !== 'consumer' &&
+    monacoMode !== monacoModeList.UIForm &&
+    targetPluginName !== 'key-auth';
 
   return (
     <Drawer
diff --git a/web/src/components/Plugin/UI/cors.tsx b/web/src/components/Plugin/UI/cors.tsx
index b639bb1..5c2bbd2 100644
--- a/web/src/components/Plugin/UI/cors.tsx
+++ b/web/src/components/Plugin/UI/cors.tsx
@@ -28,7 +28,7 @@
 
 const FORM_ITEM_LAYOUT = {
   labelCol: {
-    span: 7,
+    span: 8,
   },
   wrapperCol: {
     span: 8,
@@ -37,16 +37,20 @@
 
 export const FORM_ITEM_WITHOUT_LABEL = {
   wrapperCol: {
-    sm: { span: 8, offset: 7 },
+    sm: { span: 8, offset: 8 },
   },
 };
 
 const Cors: React.FC<Props> = ({ form, schema }) => {
   const { formatMessage } = useIntl();
-  const properties = schema?.properties
-  const regexPro = properties.allow_origins_by_regex
-  const { minLength, maxLength } = regexPro.items
-  const regexInit = Array(regexPro.minItems).join('.').split('.')
+  const properties = schema?.properties;
+  const regexPro = properties.allow_origins_by_regex;
+  const metadataPro = properties.allow_origins_by_metadata;
+
+  const { minLength, maxLength } = regexPro.items;
+  const { minLength: metadataMinLength, maxLength: metadataMaxLength } = metadataPro.items;
+  const regexInit = Array(regexPro.minItems).join('.').split('.');
+  const metadataInit = Array(metadataPro.minItems).join('.').split('.');
 
   const HTTPMethods: React.FC = () => (
     <Form.Item
@@ -55,10 +59,7 @@
     >
       <Row>
         <Col span={24}>
-          <Form.Item
-            name="allow_methods"
-            initialValue={[properties.allow_methods.default]}
-          >
+          <Form.Item name="allow_methods" initialValue={[properties.allow_methods.default]}>
             <Select
               mode="multiple"
               optionLabelProp="label"
@@ -143,7 +144,53 @@
         <Switch />
       </Form.Item>
 
-      <Form.List name='allow_origins_by_regex' initialValue={regexInit}>
+      <Form.List name="allow_origins_by_metadata" initialValue={metadataInit}>
+        {(fields, { add, remove }) => {
+          return (
+            <div>
+              {fields.map((field, index) => (
+                <Form.Item
+                  {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
+                  label={index === 0 && 'allow_origins_by_metadata'}
+                  key={field.key}
+                  tooltip={formatMessage({
+                    id: 'component.pluginForm.cors.allow_origins_by_metadata.tooltip',
+                  })}
+                >
+                  <Form.Item {...field} validateTrigger={['onChange', 'onBlur']} noStyle>
+                    <Input style={{ width: '80%' }} />
+                  </Form.Item>
+                  {fields.length > metadataMinLength && (
+                    <MinusCircleOutlined
+                      className="dynamic-delete-button"
+                      style={{ margin: '0 8px' }}
+                      onClick={() => {
+                        remove(field.name);
+                      }}
+                    />
+                  )}
+                </Form.Item>
+              ))}
+              {
+                <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
+                  {fields.length < metadataMaxLength && (
+                    <Button
+                      type="dashed"
+                      onClick={() => {
+                        add();
+                      }}
+                    >
+                      <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
+                    </Button>
+                  )}
+                </Form.Item>
+              }
+            </div>
+          );
+        }}
+      </Form.List>
+
+      <Form.List name="allow_origins_by_regex" initialValue={regexInit}>
         {(fields, { add, remove }) => {
           return (
             <div>
@@ -159,7 +206,7 @@
                   <Form.Item {...field} validateTrigger={['onChange', 'onBlur']} noStyle>
                     <Input style={{ width: '80%' }} />
                   </Form.Item>
-                  {fields.length > minLength &&
+                  {fields.length > minLength && (
                     <MinusCircleOutlined
                       className="dynamic-delete-button"
                       style={{ margin: '0 8px' }}
@@ -167,20 +214,22 @@
                         remove(field.name);
                       }}
                     />
-                  }
+                  )}
                 </Form.Item>
               ))}
               {
                 <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
-                  {fields.length < maxLength && <Button
-                    type="dashed"
-                    data-cy="add-allow_origins_by_regex"
-                    onClick={() => {
-                      add();
-                    }}
-                  >
-                    <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
-                  </Button>}
+                  {fields.length < maxLength && (
+                    <Button
+                      type="dashed"
+                      data-cy="add-allow_origins_by_regex"
+                      onClick={() => {
+                        add();
+                      }}
+                    >
+                      <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
+                    </Button>
+                  )}
                 </Form.Item>
               }
             </div>
diff --git a/web/src/components/Plugin/UI/limit-count.tsx b/web/src/components/Plugin/UI/limit-count.tsx
index 15eb595..29c359e 100644
--- a/web/src/components/Plugin/UI/limit-count.tsx
+++ b/web/src/components/Plugin/UI/limit-count.tsx
@@ -239,7 +239,8 @@
   const properties = schema?.properties;
   const [policy, setPoicy] = useState<PolicyProps>(properties.policy.default);
   const { formatMessage } = useIntl();
-  const dependSchema = schema?.dependencies.policy.oneOf;
+  const redisSchema = schema?.then;
+  const redisClusterSchema = schema?.else.then;
 
   return (
     <Form form={form} {...FORM_ITEM_LAYOUT}>
@@ -367,8 +368,8 @@
           setPoicy(form.getFieldValue('policy'));
         }}
       </Form.Item>
-      {Boolean(policy === 'redis') && <RedisForm schema={dependSchema[1]} />}
-      {Boolean(policy === 'redis-cluster') && <RedisClusterForm schema={dependSchema[2]} />}
+      {Boolean(policy === 'redis') && <RedisForm schema={redisSchema} />}
+      {Boolean(policy === 'redis-cluster') && <RedisClusterForm schema={redisClusterSchema} />}
     </Form>
   );
 };
diff --git a/web/src/components/Plugin/UI/proxy-mirror.tsx b/web/src/components/Plugin/UI/proxy-mirror.tsx
index 5b19cab..4fca5a0 100644
--- a/web/src/components/Plugin/UI/proxy-mirror.tsx
+++ b/web/src/components/Plugin/UI/proxy-mirror.tsx
@@ -26,7 +26,7 @@
 
 const FORM_ITEM_LAYOUT = {
   labelCol: {
-    span: 4,
+    span: 6,
   },
   wrapperCol: {
     span: 10,
@@ -42,15 +42,30 @@
       <Form.Item
         label="host"
         name="host"
+        required
         extra={formatMessage({ id: 'component.pluginForm.proxy-mirror.host.extra' })}
         tooltip={formatMessage({ id: 'component.pluginForm.proxy-mirror.host.tooltip' })}
         rules={[
           {
+            required: true,
             pattern: new RegExp(`${properties.host.pattern}`, 'g'),
             message: formatMessage({ id: 'component.pluginForm.proxy-mirror.host.ruletip' }),
           },
         ]}
       >
+        <Input required />
+      </Form.Item>
+      <Form.Item
+        label="path"
+        name="path"
+        tooltip={formatMessage({ id: 'component.pluginForm.proxy-mirror.path.tooltip' })}
+        rules={[
+          {
+            pattern: new RegExp(`${properties.path.pattern}`, 'g'),
+            message: formatMessage({ id: 'component.pluginForm.proxy-mirror.path.ruletip' }),
+          },
+        ]}
+      >
         <Input />
       </Form.Item>
       <Form.Item
diff --git a/web/src/components/Plugin/data.tsx b/web/src/components/Plugin/data.tsx
index 0f40f04..7b1d499 100644
--- a/web/src/components/Plugin/data.tsx
+++ b/web/src/components/Plugin/data.tsx
@@ -269,4 +269,43 @@
   'aws-lambda': {
     type: PluginType.serverless,
   },
+  'clickhouse-logger': {
+    type: PluginType.observability,
+  },
+  'client-control': {
+    type: PluginType.traffic,
+  },
+  csrf: {
+    type: PluginType.security,
+  },
+  'ext-plugin-post-req': {
+    type: PluginType.other,
+  },
+  'ext-plugin-pre-req': {
+    type: PluginType.other,
+  },
+  'file-logger': {
+    type: PluginType.observability,
+  },
+  gzip: {
+    type: PluginType.other,
+  },
+  loggly: {
+    type: PluginType.observability,
+  },
+  'public-api': {
+    type: PluginType.security,
+  },
+  'real-ip': {
+    type: PluginType.other,
+  },
+  'authz-casdoor': {
+    type: PluginType.authentication,
+  },
+  mocking: {
+    type: PluginType.other,
+  },
+  opentelemetry: {
+    type: PluginType.observability,
+  },
 };
diff --git a/web/src/components/Plugin/locales/en-US.ts b/web/src/components/Plugin/locales/en-US.ts
index f87b8da..b7d6a70 100644
--- a/web/src/components/Plugin/locales/en-US.ts
+++ b/web/src/components/Plugin/locales/en-US.ts
@@ -46,6 +46,8 @@
     'Maximum number of seconds the results can be cached. Within this time range, the browser will reuse the last check result. -1 means no cache. Please note that the maximum value is depended on browser, please refer to MDN for details.',
   'component.pluginForm.cors.allow_credential.tooltip':
     "If you set this option to true, you can not use '*' for other options.",
+  'component.pluginForm.cors.allow_origins_by_metadata.tooltip':
+    'Match which origin is allowed to enable CORS by referencing allow_origins set in plugin metadata.',
   'component.pluginForm.cors.allow_origins_by_regex.tooltip':
     'Use regex expressions to match which origin is allowed to enable CORS, for example, [".*.test.com"] can use to match all subdomain of test.com.',
 
@@ -78,6 +80,9 @@
   'component.pluginForm.proxy-mirror.host.extra': 'e.g. http://127.0.0.1:9797',
   'component.pluginForm.proxy-mirror.host.ruletip':
     'address needs to contain schema: http or https, not URI part',
+  'component.pluginForm.proxy-mirror.path.tooltip':
+    "Specify the mirror request's path part. Without it the current path will be used.",
+  'component.pluginForm.proxy-mirror.path.ruletip': 'Please enter the correct path, e.g. /path',
   'component.pluginForm.proxy-mirror.sample_ratio.tooltip':
     'the sample ratio that requests will be mirrored.',
 
diff --git a/web/src/components/Plugin/locales/zh-CN.ts b/web/src/components/Plugin/locales/zh-CN.ts
index 41ed113..6368d16 100644
--- a/web/src/components/Plugin/locales/zh-CN.ts
+++ b/web/src/components/Plugin/locales/zh-CN.ts
@@ -45,6 +45,8 @@
     '浏览器缓存 CORS 结果的最大时间,单位为秒,在这个时间范围内浏览器会复用上一次的检查结果,-1 表示不缓存。',
   'component.pluginForm.cors.allow_credential.tooltip':
     '是否允许跨域访问的请求方携带凭据(如 Cookie 等)。根据 CORS 规范,如果设置该选项为 true,那么将不能在其他选项中使用 * 。',
+  'component.pluginForm.cors.allow_origins_by_metadata.tooltip':
+    '通过引用插件元数据的 allow_origins 配置允许跨域访问的 Origin。',
   'component.pluginForm.cors.allow_origins_by_regex.tooltip':
     '使用正则表达式数组来匹配允许跨域访问的 Origin, 如[".*.test.com"] 可以匹配任何test.com的子域名 * 。',
 
@@ -73,6 +75,9 @@
   'component.pluginForm.proxy-mirror.host.extra': '例如:http://127.0.0.1:9797',
   'component.pluginForm.proxy-mirror.host.ruletip':
     '地址中需要包含 schema :http或https,不能包含 URI 部分',
+  'component.pluginForm.proxy-mirror.path.tooltip':
+    '指定镜像请求的路径。如不指定,当前路径将被使用。',
+  'component.pluginForm.proxy-mirror.path.ruletip': '请输入正确的路径,例如: /path',
   'component.pluginForm.proxy-mirror.sample_ratio.tooltip': '镜像请求采样率',
 
   // limit-conn
diff --git a/web/src/components/Upstream/components/ServiceDiscovery.tsx b/web/src/components/Upstream/components/ServiceDiscovery.tsx
index deda648..cbd6eb4 100644
--- a/web/src/components/Upstream/components/ServiceDiscovery.tsx
+++ b/web/src/components/Upstream/components/ServiceDiscovery.tsx
@@ -32,6 +32,7 @@
     args: ['group_name', 'namespace_id'],
   },
   eureka: {},
+  kubernetes: {},
 };
 
 const ServiceDiscovery: React.FC<Props> = ({ readonly, form }) => {
diff --git a/web/src/components/Upstream/locales/en-US.ts b/web/src/components/Upstream/locales/en-US.ts
index 0d82232..b1ba0fe 100644
--- a/web/src/components/Upstream/locales/en-US.ts
+++ b/web/src/components/Upstream/locales/en-US.ts
@@ -31,6 +31,7 @@
   'component.upstream.fields.discovery_type.type.consul_kv': 'Consul KV',
   'component.upstream.fields.discovery_type.type.nacos': 'Nacos',
   'component.upstream.fields.discovery_type.type.eureka': 'Eureka',
+  'component.upstream.fields.discovery_type.type.kubernetes': 'Kubernetes',
 
   'component.upstream.fields.discovery_args.group_name': 'Group Name',
   'component.upstream.fields.discovery_args.group_name.tooltip': 'Group Name',
diff --git a/web/src/components/Upstream/locales/zh-CN.ts b/web/src/components/Upstream/locales/zh-CN.ts
index 4e1dc10..5de7c6e 100644
--- a/web/src/components/Upstream/locales/zh-CN.ts
+++ b/web/src/components/Upstream/locales/zh-CN.ts
@@ -31,6 +31,7 @@
   'component.upstream.fields.discovery_type.type.consul_kv': 'Consul KV',
   'component.upstream.fields.discovery_type.type.nacos': 'Nacos',
   'component.upstream.fields.discovery_type.type.eureka': 'Eureka',
+  'component.upstream.fields.discovery_type.type.kubernetes': 'Kubernetes',
 
   'component.upstream.fields.discovery_args.group_name': '分组名',
   'component.upstream.fields.discovery_args.group_name.tooltip': '分组名',