From cbcac5f74b1da44540603493f0f4bfe417de414b Mon Sep 17 00:00:00 2001 From: Zeping Bai Date: Thu, 2 Dec 2021 10:21:23 +0800 Subject: [PATCH] feat: support post args advanced match (#2231) --- ...-with-advanced-matching-conditions.spec.js | 10 +++---- .../components/Step1/MatchingRulesView.tsx | 26 ++++++++++++++++--- web/src/pages/Route/locales/en-US.ts | 9 ++++++- web/src/pages/Route/locales/zh-CN.ts | 8 +++++- web/src/pages/Route/transform.ts | 11 +++++--- web/src/pages/Route/typing.d.ts | 2 +- 6 files changed, 50 insertions(+), 16 deletions(-) diff --git a/web/cypress/integration/route/create-route-with-advanced-matching-conditions.spec.js b/web/cypress/integration/route/create-route-with-advanced-matching-conditions.spec.js index ae4a2fc25f..45cc98dff8 100644 --- a/web/cypress/integration/route/create-route-with-advanced-matching-conditions.spec.js +++ b/web/cypress/integration/route/create-route-with-advanced-matching-conditions.spec.js @@ -23,7 +23,6 @@ context('Create Route with advanced matching conditions', () => { nodes_0_port: '#submitNodes_0_port', nodes_0_weight: '#submitNodes_0_weight', deleteAlert: '.ant-modal-body', - notificationCloseIcon: '.ant-notification-close-icon', notification: '.ant-notification-notice-message', parameterPosition: '#position', ruleCard: '.ant-modal', @@ -79,7 +78,7 @@ context('Create Route with advanced matching conditions', () => { .click() .then(() => { cy.get('.ant-select-dropdown').within(() => { - cy.contains('Build-in').should('be.visible').click(); + cy.contains('Built-in').should('be.visible').click(); }); }); cy.get(selector.ruleCard).within(() => { @@ -94,7 +93,7 @@ context('Create Route with advanced matching conditions', () => { cy.get(selector.advancedMatchingTable).should('exist'); cy.wrap(opreatorList).each((operator, index) => { cy.get(selector.advancedMatchingTableCell).within(() => { - cy.contains('td', 'Build-in Parameter').should('be.visible'); + cy.contains('td', 'Built-in Parameter').should('be.visible'); cy.contains('td', data.matchingParamName).should('be.visible'); cy.contains('td', matchingValueList1[index]).should('be.visible'); }); @@ -128,14 +127,14 @@ context('Create Route with advanced matching conditions', () => { }); }); cy.get(selector.ruleCard).within(() => { - cy.get(`[title="Build-in Parameter"]`).should('have.class', 'ant-select-selection-item'); + cy.get(`[title="Built-in Parameter"]`).should('have.class', 'ant-select-selection-item'); cy.get(selector.name).clear().type(data.matchingParamName); cy.get(`[title="${opreator}"]`).should('have.class', 'ant-select-selection-item'); cy.get(selector.value).clear().type(matchingValueList2[index]); cy.contains('Confirm').click(); }); cy.get(selector.advancedMatchingTableCell).within(() => { - cy.contains('td', 'Build-in Parameter').should('be.visible'); + cy.contains('td', 'Built-in Parameter').should('be.visible'); cy.contains('td', data.matchingParamName).should('be.visible'); cy.contains('td', matchingValueList2[index]).should('be.visible'); }); @@ -183,6 +182,5 @@ context('Create Route with advanced matching conditions', () => { cy.contains('OK').click(); }); cy.get(selector.notification).should('contain', data.deleteRouteSuccess); - cy.get(selector.notificationCloseIcon).click(); }); }); diff --git a/web/src/pages/Route/components/Step1/MatchingRulesView.tsx b/web/src/pages/Route/components/Step1/MatchingRulesView.tsx index ccbb97c511..90760a3ee8 100644 --- a/web/src/pages/Route/components/Step1/MatchingRulesView.tsx +++ b/web/src/pages/Route/components/Step1/MatchingRulesView.tsx @@ -15,11 +15,13 @@ * limitations under the License. */ import React, { useState } from 'react'; -import { Button, Table, Modal, Form, Select, Input, Space, notification } from 'antd'; +import { Button, Table, Modal, Form, Select, Input, Space, notification, Typography } from 'antd'; import { useIntl } from 'umi'; import PanelSection from '@/components/PanelSection'; +const { Title, Text } = Typography; + const MatchingRulesView: React.FC = ({ advancedMatchingRules, disabled, @@ -113,11 +115,14 @@ const MatchingRulesView: React.FC = ({ case 'arg': renderText = formatMessage({ id: 'page.route.requestParameter' }); break; + case 'post_arg': + renderText = formatMessage({ id: 'page.route.postRequestParameter' }); + break; case 'cookie': renderText = 'Cookie'; break; case 'buildin': - renderText = formatMessage({ id: 'page.route.buildinParameter' }); + renderText = formatMessage({ id: 'page.route.builtinParameter' }); break; default: renderText = ''; @@ -208,8 +213,13 @@ const MatchingRulesView: React.FC = ({ > + - + = ({ > + + {formatMessage({ id: 'page.route.advanced-match.message' })} + + {formatMessage({ id: 'page.route.advanced-match.tips.requestParameter' })} +
+ {formatMessage({ id: 'page.route.advanced-match.tips.postRequestParameter' })} +
+ {formatMessage({ id: 'page.route.advanced-match.tips.builtinParameter' })} +
+
); diff --git a/web/src/pages/Route/locales/en-US.ts b/web/src/pages/Route/locales/en-US.ts index 23c918425d..db782127af 100644 --- a/web/src/pages/Route/locales/en-US.ts +++ b/web/src/pages/Route/locales/en-US.ts @@ -23,7 +23,8 @@ export default { 'page.route.parameterPosition': 'Parameter Position', 'page.route.httpRequestHeader': 'HTTP Request Header', 'page.route.requestParameter': 'Request Parameter', - 'page.route.buildinParameter': 'Build-in Parameter', + 'page.route.postRequestParameter': 'POST Request Parameter', + 'page.route.builtinParameter': 'Built-in Parameter', 'page.route.parameterName': 'Parameter Name', 'page.route.operationalCharacter': 'Operational Character', 'page.route.equal': 'Equal(==)', @@ -182,6 +183,12 @@ export default { 'If you do not bind the service, you must set the Upstream (Step 2)', 'page.route.advanced-match.tooltip': 'It supports route matching through request headers, request parameters and cookies, and can be applied to scenarios such as grayscale publishing and blue-green testing.', + 'page.route.advanced-match.message': 'Tips', + 'page.route.advanced-match.tips.requestParameter': 'Request Parameter:Query of the request URL', + 'page.route.advanced-match.tips.postRequestParameter': + 'POST Request Parameter:Only support x-www-form-urlencoded form', + 'page.route.advanced-match.tips.builtinParameter': + 'Build-in Parameter:Nginx internal parameters', 'page.route.fields.custom.redirectOption.tooltip': 'This is related to redirect plugin', 'page.route.fields.service_id.tooltip': 'Bind Service object to reuse their configuration.', diff --git a/web/src/pages/Route/locales/zh-CN.ts b/web/src/pages/Route/locales/zh-CN.ts index 30112ab213..64adf5e3fd 100644 --- a/web/src/pages/Route/locales/zh-CN.ts +++ b/web/src/pages/Route/locales/zh-CN.ts @@ -19,7 +19,8 @@ export default { 'page.route.parameterPosition': '参数位置', 'page.route.httpRequestHeader': 'HTTP 请求头', 'page.route.requestParameter': '请求参数', - 'page.route.buildinParameter': '内置参数', + 'page.route.postRequestParameter': 'POST 请求参数', + 'page.route.builtinParameter': '内置参数', 'page.route.parameterName': '参数名称', 'page.route.operationalCharacter': '运算符', 'page.route.equal': '等于(==)', @@ -178,6 +179,11 @@ export default { 'page.route.fields.service_id.without-upstream': '如果不绑定服务,则必须设置上游服务(步骤 2)', 'page.route.advanced-match.tooltip': '支持通过请求头,请求参数、Cookie 进行路由匹配,可应用于灰度发布,蓝绿测试等场景。', + 'page.route.advanced-match.message': '提示', + 'page.route.advanced-match.tips.requestParameter': '请求参数:请求 URL 中的 Query 部分', + 'page.route.advanced-match.tips.postRequestParameter': + 'POST 请求参数:仅支持 POST x-www-form-urlencoded 表单', + 'page.route.advanced-match.tips.builtinParameter': '内置参数:Nginx 内部参数', 'page.route.fields.custom.redirectOption.tooltip': '在此配置 redirect 插件', 'page.route.fields.service_id.tooltip': '绑定服务(Service)对象,以便复用其中的配置。', diff --git a/web/src/pages/Route/transform.ts b/web/src/pages/Route/transform.ts index d1fbd3022e..a8a4f8a211 100644 --- a/web/src/pages/Route/transform.ts +++ b/web/src/pages/Route/transform.ts @@ -160,6 +160,9 @@ export const transformStepData = ({ case 'arg': key = `arg_${name}`; break; + case 'post_arg': + key = `post_arg_${name}`; + break; default: key = `${name}`; } @@ -272,11 +275,11 @@ const transformVarsToRules = ( data.map(([key, operator, value]) => { let position = ''; let name = ''; - const regex = new RegExp('^(cookie|http|arg)_.+'); + const regex = new RegExp('^(cookie|http|arg|post_arg)_.+'); if (regex.test(key)) { - [, position, name] = key.split(/^(cookie|http|arg)_/); - }else { - position = "buildin"; + [, position, name] = key.split(/^(cookie|http|arg|post_arg)_/); + } else { + position = 'buildin'; name = key; } return { diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts index 4870e380e9..5d16958e10 100644 --- a/web/src/pages/Route/typing.d.ts +++ b/web/src/pages/Route/typing.d.ts @@ -17,7 +17,7 @@ declare namespace RouteModule { type Operator = '==' | '~=' | '>' | '<' | '~~' | '~*' | 'IN' | 'HAS' | '!'; - type VarPosition = 'arg' | 'http' | 'cookie' | 'buildin'; + type VarPosition = 'arg' | 'post_arg' | 'http' | 'cookie' | 'buildin'; type RequestProtocol = 'https' | 'http' | 'websocket';