From 825358630933e751c323ebb216cc0c8f078e0173 Mon Sep 17 00:00:00 2001 From: Qi Guo <979918879@qq.com> Date: Mon, 13 Jun 2022 09:36:17 +0800 Subject: [PATCH] feat: basic support Apache APISIX 2.14.1 (#2464) --- api/conf/schema.json | 387 ++++++++++++++++-- web/cypress/fixtures/plugin-dataset.json | 5 + ...sumer-with-api-breaker-plugin-form.spec.js | 13 +- web/src/components/Plugin/UI/api-breaker.tsx | 124 ++++-- web/src/components/Plugin/locales/en-US.ts | 4 + web/src/components/Plugin/locales/tr-TR.ts | 104 ++--- web/src/components/Plugin/locales/zh-CN.ts | 2 + 7 files changed, 533 insertions(+), 106 deletions(-) diff --git a/api/conf/schema.json b/api/conf/schema.json index fd88252be6..08a3b2eebb 100644 --- a/api/conf/schema.json +++ b/api/conf/schema.json @@ -348,12 +348,12 @@ "type": "string" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "hosts": { "items": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "minItems": 1, @@ -398,6 +398,7 @@ "OPTIONS", "PATCH", "POST", + "PURGE", "PUT", "TRACE" ], @@ -631,7 +632,7 @@ "type": "object" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "http_path": { @@ -960,7 +961,7 @@ "items": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "metadata": { @@ -1014,12 +1015,13 @@ }, "scheme": { "default": "http", - "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp.", + "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp. For specific protocols, it can be kafka.", "enum": [ "grpc", "grpcs", "http", "https", + "kafka", "tcp", "tls", "udp" @@ -1079,7 +1081,7 @@ "type": "integer" }, "upstream_host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" } }, @@ -1134,7 +1136,7 @@ }, "hosts": { "items": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "minItems": 1, @@ -1253,7 +1255,7 @@ "type": "object" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "http_path": { @@ -1582,7 +1584,7 @@ "items": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "metadata": { @@ -1636,12 +1638,13 @@ }, "scheme": { "default": "http", - "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp.", + "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp. For specific protocols, it can be kafka.", "enum": [ "grpc", "grpcs", "http", "https", + "kafka", "tcp", "tls", "udp" @@ -1701,7 +1704,7 @@ "type": "integer" }, "upstream_host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" } }, @@ -1821,12 +1824,12 @@ "type": "object" }, "sni": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "snis": { "items": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "minItems": 1, @@ -1879,6 +1882,58 @@ "plugins": { "type": "object" }, + "protocol": { + "properties": { + "conf": { + "description": "protocol-specific configuration", + "type": "object" + }, + "logger": { + "items": { + "dependencies": { + "name": [ + "conf" + ] + }, + "properties": { + "conf": { + "description": "logger plugin configuration", + "type": "object" + }, + "filter": { + "description": "logger filter rules", + "type": "array" + }, + "name": { + "type": "string" + } + } + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "superior_id": { + "anyOf": [ + { + "maxLength": 64, + "minLength": 1, + "pattern": "^[a-zA-Z0-9-_.]+$", + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ] + } + }, + "required": [ + "name" + ], + "type": "object" + }, "remote_addr": { "anyOf": [ { @@ -1937,7 +1992,7 @@ }, "sni": { "description": "server name indication", - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "update_time": { @@ -2012,7 +2067,7 @@ "type": "object" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "http_path": { @@ -2341,7 +2396,7 @@ "items": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "metadata": { @@ -2395,12 +2450,13 @@ }, "scheme": { "default": "http", - "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp.", + "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp. For specific protocols, it can be kafka.", "enum": [ "grpc", "grpcs", "http", "https", + "kafka", "tcp", "tls", "udp" @@ -2460,7 +2516,7 @@ "type": "integer" }, "upstream_host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" } }, @@ -2552,7 +2608,7 @@ "type": "object" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "http_path": { @@ -2881,7 +2937,7 @@ "items": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "metadata": { @@ -2935,12 +2991,13 @@ }, "scheme": { "default": "http", - "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp.", + "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp. For specific protocols, it can be kafka.", "enum": [ "grpc", "grpcs", "http", "https", + "kafka", "tcp", "tls", "udp" @@ -3000,7 +3057,7 @@ "type": "integer" }, "upstream_host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" } }, @@ -3021,11 +3078,30 @@ "schema": { "$comment": "this is a mark for our injected plugin schema", "properties": { + "break_response_body": { + "type": "string" + }, "break_response_code": { "maximum": 599, "minimum": 200, "type": "integer" }, + "break_response_headers": { + "items": { + "properties": { + "key": { + "minLength": 1, + "type": "string" + }, + "value": { + "minLength": 1, + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, "disable": { "type": "boolean" }, @@ -3159,6 +3235,39 @@ }, "version": 0.1 }, + "authz-casdoor": { + "priority": 2559, + "schema": { + "$comment": "this is a mark for our injected plugin schema", + "properties": { + "callback_url": { + "pattern": "^[^%?]+[^/]$", + "type": "string" + }, + "client_id": { + "type": "string" + }, + "client_secret": { + "type": "string" + }, + "disable": { + "type": "boolean" + }, + "endpoint_addr": { + "pattern": "^[^%?]+[^/]$", + "type": "string" + } + }, + "required": [ + "callback_url", + "client_id", + "client_secret", + "endpoint_addr" + ], + "type": "object" + }, + "version": 0.1 + }, "authz-keycloak": { "priority": 2000, "schema": { @@ -3303,6 +3412,11 @@ "default": false, "type": "boolean" }, + "password_grant_token_generation_incoming_uri": { + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, "permissions": { "default": {}, "items": { @@ -3702,6 +3816,7 @@ "OPTIONS", "PATCH", "POST", + "PURGE", "PUT", "TRACE" ], @@ -4088,7 +4203,7 @@ }, "host": { "1": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "description": "Deprecated, use `tcp.host` instead." @@ -4157,7 +4272,7 @@ "tcp": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "port": { @@ -4295,6 +4410,44 @@ }, "version": 0.1 }, + "ext-plugin-post-resp": { + "priority": -4000, + "schema": { + "$comment": "this is a mark for our injected plugin schema", + "properties": { + "allow_degradation": { + "default": false, + "type": "boolean" + }, + "conf": { + "items": { + "properties": { + "name": { + "maxLength": 128, + "minLength": 1, + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "disable": { + "type": "boolean" + } + }, + "type": "object" + }, + "version": 0.1 + }, "ext-plugin-pre-req": { "priority": 12000, "schema": { @@ -4469,6 +4622,15 @@ }, "type": "array" }, + "request_method": { + "default": "GET", + "description": "the method for client to request the authorization service", + "enum": [ + "GET", + "POST" + ], + "type": "string" + }, "ssl_verify": { "default": true, "type": "boolean" @@ -5328,6 +5490,10 @@ "default": "apikey", "type": "string" }, + "hide_credentials": { + "default": false, + "type": "boolean" + }, "query": { "default": "apikey", "type": "string" @@ -6458,6 +6624,10 @@ "disable": { "type": "boolean" }, + "recursive": { + "default": false, + "type": "boolean" + }, "source": { "minLength": 1, "type": "string" @@ -6578,7 +6748,7 @@ "properties": { "blacklist": { "items": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "minItems": 1, @@ -6599,7 +6769,7 @@ }, "whitelist": { "items": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "minItems": 1, @@ -6618,6 +6788,7 @@ "algorithm": { "default": "uuid", "enum": [ + "nanoid", "snowflake", "uuid" ], @@ -6686,7 +6857,22 @@ "priority": 899, "schema": { "$comment": "this is a mark for our injected plugin schema", - "minProperties": 1, + "dependencies": { + "filters": { + "not": { + "required": [ + "body" + ] + } + }, + "body": { + "not": { + "required": [ + "filters" + ] + } + } + }, "properties": { "body": { "description": "new body for response", @@ -6700,6 +6886,44 @@ "disable": { "type": "boolean" }, + "filters": { + "description": "a group of filters that modify response bodyby replacing one specified string by another", + "items": { + "description": "filter that modifies response body", + "properties": { + "options": { + "default": "jo", + "description": "regex options", + "type": "string" + }, + "regex": { + "description": "match pattern on response body", + "minLength": 1, + "type": "string" + }, + "replace": { + "description": "regex substitution content", + "type": "string" + }, + "scope": { + "default": "once", + "description": "regex substitution range", + "enum": [ + "global", + "once" + ], + "type": "string" + } + }, + "required": [ + "regex", + "replace" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, "headers": { "description": "new headers for response", "minProperties": 1, @@ -7222,7 +7446,7 @@ "type": "integer" }, "name": { - "default": "sys logger", + "default": "http sys logger", "type": "string" }, "pool_size": { @@ -7251,7 +7475,7 @@ "type": "string" }, "timeout": { - "default": 3, + "default": 3000, "minimum": 1, "type": "integer" }, @@ -7436,7 +7660,7 @@ "type": "object" }, "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "http_path": { @@ -7765,7 +7989,7 @@ "items": { "properties": { "host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" }, "metadata": { @@ -7819,12 +8043,13 @@ }, "scheme": { "default": "http", - "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp.", + "description": "The scheme of the upstream. For L7 proxy, it can be one of grpc/grpcs/http/https. For L4 proxy, it can be one of tcp/tls/udp. For specific protocols, it can be kafka.", "enum": [ "grpc", "grpcs", "http", "https", + "kafka", "tcp", "tls", "udp" @@ -7884,7 +8109,7 @@ "type": "integer" }, "upstream_host": { - "pattern": "^\\*?[0-9a-zA-Z-._]+$", + "pattern": "^\\*?[0-9a-zA-Z-._\\[\\]:]+$", "type": "string" } }, @@ -8320,6 +8545,102 @@ "type": "object" }, "version": 0.1 + }, + "syslog": { + "metadata_schema": { + "properties": { + "log_format": { + "default": { + "@timestamp": "$time_iso8601", + "client_ip": "$remote_addr", + "host": "$host" + }, + "type": "object" + } + }, + "type": "object" + }, + "priority": 401, + "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" + }, + "disable": { + "type": "boolean" + }, + "drop_limit": { + "default": 1048576, + "type": "integer" + }, + "flush_limit": { + "default": 4096, + "minimum": 1, + "type": "integer" + }, + "host": { + "type": "string" + }, + "inactive_timeout": { + "default": 5, + "minimum": 1, + "type": "integer" + }, + "max_retry_count": { + "default": 0, + "minimum": 0, + "type": "integer" + }, + "name": { + "default": "stream sys logger", + "type": "string" + }, + "pool_size": { + "default": 5, + "minimum": 5, + "type": "integer" + }, + "port": { + "type": "integer" + }, + "retry_delay": { + "default": 1, + "minimum": 0, + "type": "integer" + }, + "sock_type": { + "default": "tcp", + "enum": [ + "tcp", + "udp" + ], + "type": "string" + }, + "timeout": { + "default": 3000, + "minimum": 1, + "type": "integer" + }, + "tls": { + "default": false, + "type": "boolean" + } + }, + "required": [ + "host", + "port" + ], + "type": "object" + }, + "version": 0.1 } } } diff --git a/web/cypress/fixtures/plugin-dataset.json b/web/cypress/fixtures/plugin-dataset.json index f56bb37eb4..12a2762229 100644 --- a/web/cypress/fixtures/plugin-dataset.json +++ b/web/cypress/fixtures/plugin-dataset.json @@ -67,6 +67,11 @@ "shouldValid": true, "data": { "break_response_code": 502, + "break_response_body": "{\"message\":\"breaker opened.\"}", + "break_response_headers": [ + { "key": "Content-Type", "value": "application/json" }, + { "key": "Content-Type", "value": "application/json+v1" } + ], "unhealthy": { "http_statuses": [500], "failures": 1 diff --git a/web/cypress/integration/consumer/create-consumer-with-api-breaker-plugin-form.spec.js b/web/cypress/integration/consumer/create-consumer-with-api-breaker-plugin-form.spec.js index a5f2c09542..9cbba4fb90 100644 --- a/web/cypress/integration/consumer/create-consumer-with-api-breaker-plugin-form.spec.js +++ b/web/cypress/integration/consumer/create-consumer-with-api-breaker-plugin-form.spec.js @@ -19,6 +19,9 @@ context('Create and delete consumer with api-breaker plugin form', () => { const selector = { break_response_code: '#break_response_code', + break_response_body: '#break_response_body', + break_response_headers_0_key: '#break_response_headers_0_key', + break_response_headers_0_value: '#break_response_headers_0_value', empty: '.ant-empty-normal', username: '#username', description: '#desc', @@ -31,6 +34,9 @@ context('Create and delete consumer with api-breaker plugin form', () => { const data = { break_response_code: 200, + break_response_body: 'breaker opened', + break_response_headers_0_key: 'Content-Type', + break_response_headers_0_value: 'application/json', consumerName: 'test_consumer', description: 'desc_by_autotest', createConsumerSuccess: 'Create Consumer Successfully', @@ -82,8 +88,13 @@ context('Create and delete consumer with api-breaker plugin form', () => { }); }); cy.get(selector.notification).should('contain', 'Invalid plugin data'); - + cy.contains('.ant-form-item', 'break_response_headers').within(() => { + cy.contains('button', 'Create').click(); + }); cy.get(selector.break_response_code).type(data.break_response_code); + cy.get(selector.break_response_body).type(data.break_response_body); + cy.get(selector.break_response_headers_0_key).type(data.break_response_headers_0_key); + cy.get(selector.break_response_headers_0_value).type(data.break_response_headers_0_value); cy.get(selector.disabledSwitcher).click(); cy.get(selector.drawer).within(() => { cy.contains('Submit').click({ diff --git a/web/src/components/Plugin/UI/api-breaker.tsx b/web/src/components/Plugin/UI/api-breaker.tsx index e2f97aae3b..a319e09624 100644 --- a/web/src/components/Plugin/UI/api-breaker.tsx +++ b/web/src/components/Plugin/UI/api-breaker.tsx @@ -16,7 +16,7 @@ */ import React from 'react'; import type { FormInstance } from 'antd/es/form'; -import { Button, Form, InputNumber } from 'antd'; +import { Button, Col, Form, Input, InputNumber, Row } from 'antd'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { useIntl } from 'umi'; @@ -30,7 +30,7 @@ const FORM_ITEM_LAYOUT = { span: 7, }, wrapperCol: { - span: 7, + span: 12, }, }; @@ -41,17 +41,20 @@ const FORM_ITEM_WITHOUT_LABEL = { }; const ApiBreaker: React.FC = ({ form, schema }) => { - const { formatMessage } = useIntl() - const propertires = schema?.properties - const un_http_statuses = propertires.unhealthy.properties.http_statuses - const un_http_default = un_http_statuses.default - const { http_statuses } = propertires.healthy.properties - const http_default = http_statuses.default + const { formatMessage } = useIntl(); + const propertires = schema?.properties; + const un_http_statuses = propertires.unhealthy.properties.http_statuses; + const un_http_default = un_http_statuses.default; + const { http_statuses } = propertires.healthy.properties; + const http_default = http_statuses.default; return (
= ({ form, schema }) => { })} validateTrigger={['onChange', 'onBlur', 'onClick']} > - + + + + + + + {(fields, { add, remove }) => { + return ( +
+ + {fields.map((field, index) => ( + + + + + + + + + + + + + { + remove(field.name); + }} + /> + + + ))} + + +
+ ); + }} +
+ = ({ form, schema }) => { })} key={field.key} > - - + + {fields.length > 1 ? ( = ({ form, schema }) => { label="unhealthy.failures" name={['unhealthy', 'failures']} initialValue={propertires.unhealthy.properties.failures.default} - tooltip={formatMessage({ id: 'component.pluginForm.api-breaker.unhealthy.failures.tooltip' })} + tooltip={formatMessage({ + id: 'component.pluginForm.api-breaker.unhealthy.failures.tooltip', + })} > @@ -149,12 +224,11 @@ const ApiBreaker: React.FC = ({ form, schema }) => { id: 'component.pluginForm.api-breaker.healthy.http_statuses.tooltip', })} > - - + + {fields.length > 1 ? ( = ({ form, schema }) => { label="healthy.successes" name={['healthy', 'successes']} initialValue={propertires.healthy.properties.successes.default} - tooltip={formatMessage({ id: 'component.pluginForm.api-breaker.healthy.successes.tooltip' })} + tooltip={formatMessage({ + id: 'component.pluginForm.api-breaker.healthy.successes.tooltip', + })} > diff --git a/web/src/components/Plugin/locales/en-US.ts b/web/src/components/Plugin/locales/en-US.ts index b7d6a705eb..144709186f 100644 --- a/web/src/components/Plugin/locales/en-US.ts +++ b/web/src/components/Plugin/locales/en-US.ts @@ -65,6 +65,10 @@ export default { // api-breaker 'component.pluginForm.api-breaker.break_response_code.tooltip': 'Return error code when unhealthy.', + 'component.pluginForm.api-breaker.break_response_body.tooltip': + 'Return body of the response message when upstream is unhealthy.', + 'component.pluginForm.api-breaker.break_response_headers.tooltip': + 'Return headers when unhealthy.', 'component.pluginForm.api-breaker.max_breaker_sec.tooltip': 'Maximum breaker time(seconds).', 'component.pluginForm.api-breaker.unhealthy.http_statuses.tooltip': 'Status codes when unhealthy.', diff --git a/web/src/components/Plugin/locales/tr-TR.ts b/web/src/components/Plugin/locales/tr-TR.ts index 86953a2a55..64a925dd72 100644 --- a/web/src/components/Plugin/locales/tr-TR.ts +++ b/web/src/components/Plugin/locales/tr-TR.ts @@ -15,7 +15,8 @@ * limitations under the License. */ export default { - 'component.plugin.tip1': 'NOT:Eklentilerinizi değiştirdikten sonra değişiklileri schema.json dosyasına uygulamalısınız.', + 'component.plugin.tip1': + 'NOT:Eklentilerinizi değiştirdikten sonra değişiklileri schema.json dosyasına uygulamalısınız.', 'component.plugin.tip2': 'Nasıl güncellenir?', 'component.select.pluginTemplate': 'Eklenti şablonlarını seçin', 'component.step.select.pluginTemplate.select.option': 'Özel', @@ -39,117 +40,124 @@ export default { 'component.pluginForm.cors.allow_headers.tooltip': 'Kaynaklar arası kaynağa erişirken istekte hangi başlıkların ayarlanmasına izin verilir. Bölmek için çoklu değer kullanımı. allow_credential false olduğunda, tüm istek üstbilgilerine izin ver belirtmek için * kullanabilirsiniz. Ayrıca, ** kullanarak herhangi bir üstbilgiye zorla izin verebilirsiniz, hatta allow_credentialı hali hazırda etkinleştirdiyseniz bu bazı güvenlik riskleri getirecektir,', 'component.pluginForm.cors.expose_headers.tooltip': - 'Başlangıçlar arası kaynağa erişildiğinde yanıt olarak hangi başlıkların ayarlanmasına izin verilir. Bölmek için çoklu değer kullanımı. allow_credential false olduğunda, herhangi bir başlığa izin ver belirtmek için * kullanabilirsiniz. Ayrıca, ** kullanarak herhangi bir üstbilgiye zorla izin verebilirsiniz, hatta allow_credentialı zaten etkinleştirin, ancak bu bazı güvenlik riskleri getirecektir.', + 'Başlangıçlar arası kaynağa erişildiğinde yanıt olarak hangi başlıkların ayarlanmasına izin verilir. Bölmek için çoklu değer kullanımı. allow_credential false olduğunda, herhangi bir başlığa izin ver belirtmek için * kullanabilirsiniz. Ayrıca, ** kullanarak herhangi bir üstbilgiye zorla izin verebilirsiniz, hatta allow_credentialı zaten etkinleştirin, ancak bu bazı güvenlik riskleri getirecektir.', 'component.pluginForm.cors.max_age.tooltip': - 'Sonuçların önbelleğe alınabileceği maksimum saniye sayısı. Bu zaman aralığında tarayıcı son kontrol sonucunu yeniden kullanır. -1 önbellek yok demektir. Lütfen maksimum değerin tarayıcıya bağlı olduğunu unutmayın, ayrıntılar için lütfen MDNye bakınız.', + 'Sonuçların önbelleğe alınabileceği maksimum saniye sayısı. Bu zaman aralığında tarayıcı son kontrol sonucunu yeniden kullanır. -1 önbellek yok demektir. Lütfen maksimum değerin tarayıcıya bağlı olduğunu unutmayın, ayrıntılar için lütfen MDNye bakınız.', 'component.pluginForm.cors.allow_credential.tooltip': - "Bu seçeneği true olarak ayarlarsanız, diğer seçenekler için '*' ı kullanamazsınız.", + "Bu seçeneği true olarak ayarlarsanız, diğer seçenekler için '*' ı kullanamazsınız.", 'component.pluginForm.cors.allow_origins_by_metadata.tooltip': - 'Eklenti meta verilerindeki allow_origins kümesine başvurarak CORSu etkinleştirmek için hangi Origine izin verildiğini eşleştirin.', + 'Eklenti meta verilerindeki allow_origins kümesine başvurarak CORSu etkinleştirmek için hangi Origine izin verildiğini eşleştirin.', 'component.pluginForm.cors.allow_origins_by_regex.tooltip': - 'CORSu etkinleştirmek için hangi Origine izin verildiğini eşleştirmek için normal ifade ifadeleri kullanın, örneğin, [".*.test.com"], test.comun tüm alt alan adlarını eşleştirmek için kullanabilir.', + 'CORSu etkinleştirmek için hangi Origine izin verildiğini eşleştirmek için normal ifade ifadeleri kullanın, örneğin, [".*.test.com"], test.comun tüm alt alan adlarını eşleştirmek için kullanabilir.', // referer-restriction 'component.pluginForm.referer-restriction.whitelist.tooltip': - 'Whiteliste alınacak ana bilgisayar adı listesi. Ana bilgisayar adı, joker karakter olarak * ile başlatılabilir.', + 'Whiteliste alınacak ana bilgisayar adı listesi. Ana bilgisayar adı, joker karakter olarak * ile başlatılabilir.', 'component.pluginForm.referer-restriction.blacklist.tooltip': -'Kara listeye alınacak ana bilgisayar adı listesi. Ana bilgisayar adı, joker karakter olarak * ile başlatılabilir.', + 'Kara listeye alınacak ana bilgisayar adı listesi. Ana bilgisayar adı, joker karakter olarak * ile başlatılabilir.', 'component.pluginForm.referer-restriction.listEmpty.tooltip': 'Boş Liste', 'component.pluginForm.referer-restriction.bypass_missing.tooltip': - 'Yönlendiren başlığı eksik veya hatalı biçimlendirilmiş olduğunda kontrolün atlanıp atlanmayacağı.', + 'Yönlendiren başlığı eksik veya hatalı biçimlendirilmiş olduğunda kontrolün atlanıp atlanmayacağı.', 'component.pluginForm.referer-restriction.message.tooltip': - 'Erişime izin verilmemesi durumunda mesaj döndürülür', + 'Erişime izin verilmemesi durumunda mesaj döndürülür', // api-breaker 'component.pluginForm.api-breaker.break_response_code.tooltip': - 'Unhealthy durum oluştuğunda hata kodunu döndür.', + 'Unhealthy durum oluştuğunda hata kodunu döndür.', + 'component.pluginForm.api-breaker.break_response_body.tooltip': + 'Sağlıksız bir durum oluştuğunda telegramları döndürür.', + 'component.pluginForm.api-breaker.break_response_headers.tooltip': + 'Sağlıksız olduğunda başlıkları döndürün.', 'component.pluginForm.api-breaker.max_breaker_sec.tooltip': 'Kesme Zamanı(Saniye)', 'component.pluginForm.api-breaker.unhealthy.http_statuses.tooltip': 'Durum Kodları (Unhealthy durumda).', 'component.pluginForm.api-breaker.unhealthy.failures.tooltip': - 'Unhealthy bir durumu tetikleyen ardışık hata isteklerinin sayısı.', - 'component.pluginForm.api-breaker.healthy.http_statuses.tooltip': 'Durum Kodları (Unhealthy durumda)', + 'Unhealthy bir durumu tetikleyen ardışık hata isteklerinin sayısı.', + 'component.pluginForm.api-breaker.healthy.http_statuses.tooltip': + 'Durum Kodları (Unhealthy durumda)', 'component.pluginForm.api-breaker.healthy.successes.tooltip': - 'Healthy durumu tetikleyen ardışık normal isteklerin sayısı.', + 'Healthy durumu tetikleyen ardışık normal isteklerin sayısı.', // proxy-mirror 'component.pluginForm.proxy-mirror.host.tooltip': - 'Bir mirror servis adresi belirtin, ör. http://127.0.0.1:9797 (adresin şema içermesi gerekir: URI kısmı değil, http veya https)', + 'Bir mirror servis adresi belirtin, ör. http://127.0.0.1:9797 (adresin şema içermesi gerekir: URI kısmı değil, http veya https)', 'component.pluginForm.proxy-mirror.host.extra': 'örn. http://127.0.0.1:9797', 'component.pluginForm.proxy-mirror.host.ruletip': 'Adres şema içermelidir http veya https, URI parçası olmamalı', 'component.pluginForm.proxy-mirror.path.tooltip': - "Yansıtma isteğinin yol bölümünü belirtin. O olmazsa mevcut yol kullanılacaktır.", + 'Yansıtma isteğinin yol bölümünü belirtin. O olmazsa mevcut yol kullanılacaktır.', 'component.pluginForm.proxy-mirror.path.ruletip': 'Lütfen doğru yolu girin, ör. /path', 'component.pluginForm.proxy-mirror.sample_ratio.tooltip': - 'isteklerin mirror edileceği örnek oranı.', + 'isteklerin mirror edileceği örnek oranı.', // limit-conn 'component.pluginForm.limit-conn.conn.tooltip': - 'izin verilen maksimum eşzamanlı istek sayısı. Bu oranı aşan (ve bağlantı + çoğuşmanın altındaki) istekler bu eşiğe uyacak şekilde ertelenir (gecikme saniyeleri default_conn_delay tarafından yapılandırılır).', + 'izin verilen maksimum eşzamanlı istek sayısı. Bu oranı aşan (ve bağlantı + çoğuşmanın altındaki) istekler bu eşiğe uyacak şekilde ertelenir (gecikme saniyeleri default_conn_delay tarafından yapılandırılır).', 'component.pluginForm.limit-conn.burst.tooltip': - 'Gecikmesine izin verilen aşırı eşzamanlı isteklerin (veya bağlantıların) sayısı.', + 'Gecikmesine izin verilen aşırı eşzamanlı isteklerin (veya bağlantıların) sayısı.', 'component.pluginForm.limit-conn.default_conn_delay.tooltip': - 'eşzamanlı istekler bağlantıyı aştığında ancak altında (conn + burst) olduğunda isteğin gecikme saniyeleri.', + 'eşzamanlı istekler bağlantıyı aştığında ancak altında (conn + burst) olduğunda isteğin gecikme saniyeleri.', 'component.pluginForm.limit-conn.key_type.tooltip': 'Anahtar tipinin destekledikleri; "var" (single var) ve "var_combination" (combine var)', 'component.pluginForm.limit-conn.key.tooltip': 'Eşzamanlılık seviyesini sınırlamak için kullanılır. Örneğin ana bilgisayar adı başına eşzamanlılığı sınırlamamız için ana bilgisayar adı (veya sunucu bölgesi) anahtar olarak kullanılabilir Aksi takdirde tek bir istemcinin hizmetimizi çok fazla bağlantı veya istekle doldurmasını önlemek için istemci adresini anahtar olarak da kullanabiliriz.', 'component.pluginForm.limit-conn.rejected_code.tooltip': - 'istek (conn + burst) aştığında döndürülen reddedilecektir.', + 'istek (conn + burst) aştığında döndürülen reddedilecektir.', 'component.pluginForm.limit-conn.rejected_msg.tooltip': - 'istek (conn + burst) aştığında döndürülen yanıt gövdesi reddedilecektir.', + 'istek (conn + burst) aştığında döndürülen yanıt gövdesi reddedilecektir.', 'component.pluginForm.limit-conn.only_use_default_delay.tooltip': - 'gecikme saniyelerinin katı modunu etkinleştirin. Bu seçeneği true olarak ayarlarsanız, ek hesaplama mantığı olmadan kesinlikle belirlediğiniz gecikme saniyelerine göre çalışır.', + 'gecikme saniyelerinin katı modunu etkinleştirin. Bu seçeneği true olarak ayarlarsanız, ek hesaplama mantığı olmadan kesinlikle belirlediğiniz gecikme saniyelerine göre çalışır.', 'component.pluginForm.limit-conn.allow_degradation.tooltip': - 'Limit-bağlantı işlevi geçici olarak kullanılamadığında eklenti bozulmasını etkinleştirip etkinleştirmeme. Değer true, varsayılan false olarak ayarlandığında isteklerin devam etmesine izin verir.', + 'Limit-bağlantı işlevi geçici olarak kullanılamadığında eklenti bozulmasını etkinleştirip etkinleştirmeme. Değer true, varsayılan false olarak ayarlandığında isteklerin devam etmesine izin verir.', // limit-req 'component.pluginForm.limit-req.rate.tooltip': - 'Belirtilen istek oranı (saniyedeki sayı) eşiği. Bu oranı aşan (ve patlamanın altındaki) istekler, orana uymak için gecikecektir.', + 'Belirtilen istek oranı (saniyedeki sayı) eşiği. Bu oranı aşan (ve patlamanın altındaki) istekler, orana uymak için gecikecektir.', 'component.pluginForm.limit-req.burst.tooltip': - 'Saniyedeki aşırı istek sayısının ertelenmesine izin verildi. Bu katı sınırı aşan istekler hemen reddedilecektir.', + 'Saniyedeki aşırı istek sayısının ertelenmesine izin verildi. Bu katı sınırı aşan istekler hemen reddedilecektir.', 'component.pluginForm.limit-req.key_type.tooltip': - 'Anahtar tipinin destekledikleri; "var" (single var) ve "var_combination" (combine var)', - 'component.pluginForm.limit-req.key.tooltip': 'Hızı sınırlamak için kullanıcı tarafından belirlenen anahtar.', + 'Anahtar tipinin destekledikleri; "var" (single var) ve "var_combination" (combine var)', + 'component.pluginForm.limit-req.key.tooltip': + 'Hızı sınırlamak için kullanıcı tarafından belirlenen anahtar.', 'component.pluginForm.limit-req.rejected_code.tooltip': - 'Talep eşiği aştığında döndürülen HTTP durum kodu reddedilir.', + 'Talep eşiği aştığında döndürülen HTTP durum kodu reddedilir.', 'component.pluginForm.limit-req.rejected_msg.tooltip': - 'Talep eşiği aştığında döndürülen yanıt body reddedilir.', + 'Talep eşiği aştığında döndürülen yanıt body reddedilir.', 'component.pluginForm.limit-req.nodelay.tooltip': - 'Gecikme bayrağı doğru değilse, engellenen istekler ertelenmez', + 'Gecikme bayrağı doğru değilse, engellenen istekler ertelenmez', 'component.plugin.form': 'Eklenti Formu', 'component.plugin.format-codes.disable': 'JSON veya YAML formatı', 'component.plugin.editor': 'Eklenti Düzenleyici', - 'component.plugin.noConfigurationRequired': "Eklenti için yapılandırma gerekli değil", + 'component.plugin.noConfigurationRequired': 'Eklenti için yapılandırma gerekli değil', // limit-count 'component.pluginForm.limit-count.count.tooltip': 'Belirtilen sayıda istek eşiği.', 'component.pluginForm.limit-count.time_window.tooltip': - 'İstek sayısı sıfırlanmadan önceki saniye cinsinden zaman penceresi.', + 'İstek sayısı sıfırlanmadan önceki saniye cinsinden zaman penceresi.', 'component.pluginForm.limit-count.key_type.tooltip': - 'Anahtar tipinin destekledikleri; "var" (single var) ve "var_combination" (combine var)', - 'component.pluginForm.limit-count.key.tooltip': 'Sayıyı sınırlamak için kullanıcı tarafından belirlenen anahtar.', + 'Anahtar tipinin destekledikleri; "var" (single var) ve "var_combination" (combine var)', + 'component.pluginForm.limit-count.key.tooltip': + 'Sayıyı sınırlamak için kullanıcı tarafından belirlenen anahtar.', 'component.pluginForm.limit-count.rejected_code.tooltip': - 'Talep eşiği aştığında döndürülen HTTP durum kodu reddedilir, varsayılan kod 503dür.', + 'Talep eşiği aştığında döndürülen HTTP durum kodu reddedilir, varsayılan kod 503dür.', 'component.pluginForm.limit-count.rejected_msg.tooltip': - 'Talep eşiği aştığında döndürülen yanıt gövdesi reddedilir.', + 'Talep eşiği aştığında döndürülen yanıt gövdesi reddedilir.', 'component.pluginForm.limit-count.policy.tooltip': - 'Sınırları almak ve artırmak için kullanılacak hız sınırlayıcı politikalar. Kullanılabilir değerler yereldir (sayaçlar düğümdeki bellekte yerel olarak depolanır) ve redis (sayaçlar bir Redis sunucusunda depolanır ve düğümler arasında paylaşılır, genellikle bunu küresel hız sınırını yapmak için kullanır) ve yeniden kümeleme (redis ile aynı işlev, yalnızca Redis küme desenini kullanın).', + 'Sınırları almak ve artırmak için kullanılacak hız sınırlayıcı politikalar. Kullanılabilir değerler yereldir (sayaçlar düğümdeki bellekte yerel olarak depolanır) ve redis (sayaçlar bir Redis sunucusunda depolanır ve düğümler arasında paylaşılır, genellikle bunu küresel hız sınırını yapmak için kullanır) ve yeniden kümeleme (redis ile aynı işlev, yalnızca Redis küme desenini kullanın).', 'component.pluginForm.limit-count.allow_degradation.tooltip': - 'Limit-count işlevi geçici olarak kullanılamadığında eklenti bozulmasının etkinleştirilip etkinleştirilmediği (ör. redis zaman aşımı). Değer true olarak ayarlandığında isteklerin devam etmesine izin verir', + 'Limit-count işlevi geçici olarak kullanılamadığında eklenti bozulmasının etkinleştirilip etkinleştirilmediği (ör. redis zaman aşımı). Değer true olarak ayarlandığında isteklerin devam etmesine izin verir', 'component.pluginForm.limit-count.show_limit_quota_header.tooltip': - 'Yanıt başlığında X-RateLimit-Limit ve X-RateLimit-Remaining (yani toplam istek sayısı ve gönderilebilecek kalan istek sayısı anlamına gelir)', + 'Yanıt başlığında X-RateLimit-Limit ve X-RateLimit-Remaining (yani toplam istek sayısı ve gönderilebilecek kalan istek sayısı anlamına gelir)', 'component.pluginForm.limit-count.group.tooltip': - 'Aynı grupla yapılandırılan rota aynı sayacı paylaşacaktır', + 'Aynı grupla yapılandırılan rota aynı sayacı paylaşacaktır', 'component.pluginForm.limit-count.redis_host.tooltip': - 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun adresini belirtir.', + 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun adresini belirtir.', 'component.pluginForm.limit-count.redis_port.tooltip': - 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun bağlantı noktasını belirtir.', + 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun bağlantı noktasını belirtir.', 'component.pluginForm.limit-count.redis_password.tooltip': - 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun parolasını belirtir.', + 'Redis ilkesini kullanırken, bu özellik Redis sunucusunun parolasını belirtir.', 'component.pluginForm.limit-count.redis_database.tooltip': - 'Redis ilkesini kullanırken, bu özellik, Redis sunucusundan seçtiğiniz veritabanını ve yalnızca Redis olmayan küme modu (tek örnek modu veya tek giriş sağlayan Redis genel bulut hizmeti) için belirtir.', + 'Redis ilkesini kullanırken, bu özellik, Redis sunucusundan seçtiğiniz veritabanını ve yalnızca Redis olmayan küme modu (tek örnek modu veya tek giriş sağlayan Redis genel bulut hizmeti) için belirtir.', 'component.pluginForm.limit-count.redis_timeout.tooltip': - 'Redis ilkesini kullanırken, bu özellik Redis sunucusuna gönderilen herhangi bir komutun zaman aşımını milisaniye cinsinden belirtir.', + 'Redis ilkesini kullanırken, bu özellik Redis sunucusuna gönderilen herhangi bir komutun zaman aşımını milisaniye cinsinden belirtir.', 'component.pluginForm.limit-count.redis_cluster_nodes.tooltip': - 'Redis-cluster ilkesi kullanılırken bu özellik, Redis küme hizmeti düğümlerinin (en az iki düğüm) adreslerinin bir listesidir.', + 'Redis-cluster ilkesi kullanılırken bu özellik, Redis küme hizmeti düğümlerinin (en az iki düğüm) adreslerinin bir listesidir.', 'component.pluginForm.limit-count.redis_cluster_name.tooltip': - 'Redis-cluster ilkesi kullanılırken, bu özellik Redis küme hizmeti düğümlerinin adıdır.', + 'Redis-cluster ilkesi kullanılırken, bu özellik Redis küme hizmeti düğümlerinin adıdır.', 'component.pluginForm.limit-count.atLeast2Characters.rule': 'Please enter at least 2 characters', }; diff --git a/web/src/components/Plugin/locales/zh-CN.ts b/web/src/components/Plugin/locales/zh-CN.ts index 6368d166fb..07b677ddb3 100644 --- a/web/src/components/Plugin/locales/zh-CN.ts +++ b/web/src/components/Plugin/locales/zh-CN.ts @@ -62,6 +62,8 @@ export default { // api-breaker 'component.pluginForm.api-breaker.break_response_code.tooltip': '不健康返回错误码。', + 'component.pluginForm.api-breaker.break_response_body.tooltip': '不健康返回报文', + 'component.pluginForm.api-breaker.break_response_headers.tooltip': '不健康返回报文头', 'component.pluginForm.api-breaker.max_breaker_sec.tooltip': '最大熔断持续时间。', 'component.pluginForm.api-breaker.unhealthy.http_statuses.tooltip': '不健康时候的状态码。', 'component.pluginForm.api-breaker.unhealthy.failures.tooltip':