This is an automated email from the ASF dual-hosted git repository. guoqi pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new bd1f6c14 feat: basic support Apache APISIX 2.13.0 (#2428)
bd1f6c14 is described below
commit bd1f6c14ec8df4f00e069a0ca69d967621145e56
Author: Qi Guo <[email protected]>
AuthorDate: Fri May 6 17:43:21 2022 +0800
feat: basic support Apache APISIX 2.13.0 (#2428)
---
api/conf/schema.json | 752 ++++++++++++++++++---
api/internal/core/store/validate_test.go | 8 +-
api/test/e2enew/consumer/consumer_test.go | 9 +-
api/test/e2enew/label/label_test.go | 3 +-
api/test/e2enew/route/route_export_test.go | 23 +-
.../route/route_with_plugin_limit_count_test.go | 12 +-
api/test/e2enew/schema/schema_test.go | 4 +-
api/test/e2enew/service/service_test.go | 6 +-
api/test/testdata/invalid-dag-conf.json | 3 +-
docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md | 1 +
web/cypress/fixtures/plugin-dataset.json | 23 +-
web/src/components/Plugin/PluginDetail.tsx | 19 +-
web/src/components/Plugin/UI/cors.tsx | 93 ++-
web/src/components/Plugin/UI/limit-count.tsx | 7 +-
web/src/components/Plugin/UI/proxy-mirror.tsx | 17 +-
web/src/components/Plugin/data.tsx | 39 ++
web/src/components/Plugin/locales/en-US.ts | 5 +
web/src/components/Plugin/locales/zh-CN.ts | 5 +
.../Upstream/components/ServiceDiscovery.tsx | 1 +
web/src/components/Upstream/locales/en-US.ts | 1 +
web/src/components/Upstream/locales/zh-CN.ts | 1 +
21 files changed, 883 insertions(+), 149 deletions(-)
diff --git a/api/conf/schema.json b/api/conf/schema.json
index a65c22ac..fd88252b 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": {
@@ -3868,6 +4028,11 @@
"tcp"
]
},
+ {
+ "required": [
+ "clickhouse"
+ ]
+ },
{
"required": [
"host",
@@ -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"
-
]
- }
- }
+ "else": {
+ "if": {
+ "properties": {
+ "policy": {
+ "enum": [
+
"redis-cluster"
+ ]
+ }
+ }
+ },
+ "then": {
+ "properties": {
+ "redis_cluster_name": {
+ "type": "string"
},
- {
- "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"
- }
+ "redis_cluster_nodes": {
+ "items": {
+
"maxLength": 100,
+
"minLength": 2,
+ "type":
"string"
},
- "required": [
-
"redis_host"
- ]
+ "minItems": 2,
+ "type": "array"
},
- {
- "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"
- ]
+ "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 c85e39a5..6ea2466e 100644
--- a/api/internal/core/store/validate_test.go
+++ b/api/internal/core/store/validate_test.go
@@ -82,8 +82,9 @@ func TestAPISIXJsonSchemaValidator_Validate(t *testing.T) {
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
- }
+ "key": "remote_addr",
+ "policy": "local"
+ }
},
"desc": "test description"
}`
@@ -105,7 +106,8 @@ func TestAPISIXJsonSchemaValidator_Validate(t *testing.T) {
"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 d420f88b..0b25bccd 100644
--- a/api/test/e2enew/consumer/consumer_test.go
+++ b/api/test/e2enew/consumer/consumer_test.go
@@ -41,7 +41,8 @@ var _ = Describe("Consumer", func() {
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
@@ -69,7 +70,8 @@ var _ = Describe("Consumer", func() {
"count": 2,
"time_window": 60,
"rejected_code": 504,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"desc": "test description"
@@ -111,7 +113,8 @@ var _ = Describe("Consumer", func() {
"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 12f5900b..954f72d8 100644
--- a/api/test/e2enew/label/label_test.go
+++ b/api/test/e2enew/label/label_test.go
@@ -109,7 +109,8 @@ var _ = ginkgo.Describe("Test label", func() {
"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 7e245dfa..de9923cc 100644
--- a/api/test/e2enew/route/route_export_test.go
+++ b/api/test/e2enew/route/route_export_test.go
@@ -66,6 +66,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -100,6 +101,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -142,7 +144,8 @@ var _ = ginkgo.Describe("Route", func() {
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"status": 1,
@@ -195,6 +198,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -229,6 +233,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 2,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -272,7 +277,8 @@ var _ = ginkgo.Describe("Route", func() {
"count": 2,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"status": 1,
@@ -376,6 +382,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -417,6 +424,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key":
"remote_addr",
+ "policy":
"local",
"rejected_code": 503,
"time_window":
60
}
@@ -455,6 +463,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"time_window": 60,
+ "policy": "local",
"rejected_code": 503,
"key": "remote_addr"
}
@@ -557,6 +566,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -598,6 +608,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key":
"remote_addr",
+ "policy":
"local",
"rejected_code": 503,
"time_window":
60
},
@@ -640,7 +651,8 @@ var _ = ginkgo.Describe("Route", func() {
"count": 100,
"time_window": 60,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream": {
@@ -746,6 +758,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key": "remote_addr",
+ "policy": "local",
"rejected_code": 503,
"time_window": 60
}
@@ -787,6 +800,7 @@ var _ = ginkgo.Describe("Route", func() {
"limit-count": {
"count": 100,
"key":
"remote_addr",
+ "policy":
"local",
"rejected_code": 503,
"time_window":
60
},
@@ -847,7 +861,8 @@ var _ = ginkgo.Describe("Route", func() {
"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 45e384bb..a25d15c1 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 @@ var _ = ginkgo.Describe("route with limit plugin", func() {
"count": 2,
"time_window": 2,
"rejected_code": 503,
- "key": "remote_addr"
+ "key": "remote_addr",
+ "policy": "local"
}
},
"upstream": {
@@ -137,7 +138,8 @@ var _ = ginkgo.Describe("route with limit plugin by
consumer", func() {
"count": 2,
"time_window": 2,
"rejected_code": 503,
- "key": "consumer_name"
+ "key": "consumer_name",
+ "policy": "local"
}
},
"upstream": {
@@ -305,7 +307,8 @@ var _ = ginkgo.Describe("route with limit count and
disable", func() {
"time_window": 2,
"rejected_code": 503,
"key": "remote_addr",
- "disable": false
+ "disable": false,
+ "policy": "local"
}
},
"upstream": {
@@ -362,7 +365,8 @@ var _ = ginkgo.Describe("route with limit count and
disable", func() {
"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 fb99b273..05127f48 100644
--- a/api/test/e2enew/schema/schema_test.go
+++ b/api/test/e2enew/schema/schema_test.go
@@ -45,7 +45,7 @@ var _ = ginkgo.Describe("Schema Test", func() {
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 @@ var _ = ginkgo.Describe("Schema Test", func() {
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 fde787b0..39643d9c 100644
--- a/api/test/e2enew/service/service_test.go
+++ b/api/test/e2enew/service/service_test.go
@@ -193,6 +193,7 @@ var _ = ginkgo.Describe("create service with plugin",
func() {
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
+ "policy": "local",
},
},
"upstream": map[string]interface{}{
@@ -225,7 +226,7 @@ var _ = ginkgo.Describe("create service with plugin",
func() {
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 @@ var _ = ginkgo.Describe("create service with all options
via POST method", func(
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
+ "policy": "local",
},
},
"upstream": map[string]interface{}{
@@ -341,7 +343,7 @@ var _ = ginkgo.Describe("create service with all options
via POST method", func(
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 c11916ae..260e06a3 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 40d1e523..bd49c14e 100644
--- a/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
+++ b/docs/en/latest/IMPORT_OPENAPI_USER_GUIDE.md
@@ -219,6 +219,7 @@ paths:
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 6f02cdeb..f56bb37e 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 fde16268..4170a156 100644
--- a/web/src/components/Plugin/PluginDetail.tsx
+++ b/web/src/components/Plugin/PluginDetail.tsx
@@ -129,10 +129,16 @@ const PluginDetail: React.FC<Props> = ({
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 PluginDetail: React.FC<Props> = ({
};
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 b639bb12..5c2bbd2e 100644
--- a/web/src/components/Plugin/UI/cors.tsx
+++ b/web/src/components/Plugin/UI/cors.tsx
@@ -28,7 +28,7 @@ type Props = {
const FORM_ITEM_LAYOUT = {
labelCol: {
- span: 7,
+ span: 8,
},
wrapperCol: {
span: 8,
@@ -37,16 +37,20 @@ const FORM_ITEM_LAYOUT = {
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 @@ const Cors: React.FC<Props> = ({ form, schema }) => {
>
<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 @@ const Cors: React.FC<Props> = ({ form, schema }) => {
<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 @@ const Cors: React.FC<Props> = ({ form, schema }) => {
<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 @@ const Cors: React.FC<Props> = ({ form, schema }) => {
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 15eb5955..29c359e8 100644
--- a/web/src/components/Plugin/UI/limit-count.tsx
+++ b/web/src/components/Plugin/UI/limit-count.tsx
@@ -239,7 +239,8 @@ const LimitCount: React.FC<Props> = ({ form, schema }) => {
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 @@ const LimitCount: React.FC<Props> = ({ form, schema }) => {
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 5b19cabb..4fca5a07 100644
--- a/web/src/components/Plugin/UI/proxy-mirror.tsx
+++ b/web/src/components/Plugin/UI/proxy-mirror.tsx
@@ -26,7 +26,7 @@ type Props = {
const FORM_ITEM_LAYOUT = {
labelCol: {
- span: 4,
+ span: 6,
},
wrapperCol: {
span: 10,
@@ -42,14 +42,29 @@ const ProxyMirror: React.FC<Props> = ({ form, schema }) => {
<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>
diff --git a/web/src/components/Plugin/data.tsx
b/web/src/components/Plugin/data.tsx
index 0f40f042..7b1d4997 100644
--- a/web/src/components/Plugin/data.tsx
+++ b/web/src/components/Plugin/data.tsx
@@ -269,4 +269,43 @@ export const PLUGIN_LIST = {
'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 f87b8da3..b7d6a705 100644
--- a/web/src/components/Plugin/locales/en-US.ts
+++ b/web/src/components/Plugin/locales/en-US.ts
@@ -46,6 +46,8 @@ export default {
'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 @@ export default {
'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 41ed113d..6368d166 100644
--- a/web/src/components/Plugin/locales/zh-CN.ts
+++ b/web/src/components/Plugin/locales/zh-CN.ts
@@ -45,6 +45,8 @@ export default {
'浏览器缓存 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 @@ export default {
'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 deda6484..cbd6eb4a 100644
--- a/web/src/components/Upstream/components/ServiceDiscovery.tsx
+++ b/web/src/components/Upstream/components/ServiceDiscovery.tsx
@@ -32,6 +32,7 @@ const discoveryType = {
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 0d822323..b1ba0fe6 100644
--- a/web/src/components/Upstream/locales/en-US.ts
+++ b/web/src/components/Upstream/locales/en-US.ts
@@ -31,6 +31,7 @@ export default {
'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 4e1dc100..5de7c6e2 100644
--- a/web/src/components/Upstream/locales/zh-CN.ts
+++ b/web/src/components/Upstream/locales/zh-CN.ts
@@ -31,6 +31,7 @@ export default {
'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': '分组名',
