From 1fd480c9bc795bcfb71d6a34c84094f9e29c9a94 Mon Sep 17 00:00:00 2001 From: liuxiran Date: Thu, 13 Aug 2020 13:45:19 +0800 Subject: [PATCH] feat(route): route add params mapping feature (#375) --- .../components/Step1/MatchingRulesView.tsx | 2 +- .../Step2/HttpHeaderRewriteView.tsx | 31 +++-- .../components/Step2/RequestRewriteView.tsx | 119 ++++++++++++++---- src/pages/Route/constants.ts | 2 + src/pages/Route/locales/en-US.ts | 3 + src/pages/Route/locales/zh-CN.ts | 3 + src/pages/Route/transform.ts | 19 +++ src/pages/Route/typing.d.ts | 3 + 8 files changed, 153 insertions(+), 29 deletions(-) diff --git a/src/pages/Route/components/Step1/MatchingRulesView.tsx b/src/pages/Route/components/Step1/MatchingRulesView.tsx index f6284d47b6..be403da3b1 100644 --- a/src/pages/Route/components/Step1/MatchingRulesView.tsx +++ b/src/pages/Route/components/Step1/MatchingRulesView.tsx @@ -165,7 +165,7 @@ const MatchingRulesView: React.FC = ({ data, disabled, onChange }) => { cancelText={formatMessage({ id: 'route.match.cancel' })} destroyOnClose > -
+ = ({ data, disabled, onChange }) => dataIndex: 'header_action', key: 'header_action', render: (action: 'override' | 'remove') => { - return action === 'override' ? formatMessage({ id: 'route.http.override.or.create' }) : formatMessage({ id: 'route.http.delete' }); + return action === 'override' + ? formatMessage({ id: 'route.http.override.or.create' }) + : formatMessage({ id: 'route.http.delete' }); }, }, { @@ -114,7 +116,11 @@ const HttpHeaderRewriteView: React.FC = ({ data, disabled, onChange }) => return ( = ({ data, disabled, onChange }) => cancelText={formatMessage({ id: 'route.http.cancel' })} destroyOnClose > - + {showModalValue && ( diff --git a/src/pages/Route/components/Step2/RequestRewriteView.tsx b/src/pages/Route/components/Step2/RequestRewriteView.tsx index 337c8100fb..8bb4616feb 100644 --- a/src/pages/Route/components/Step2/RequestRewriteView.tsx +++ b/src/pages/Route/components/Step2/RequestRewriteView.tsx @@ -38,7 +38,10 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) useEffect(() => { // eslint-disable-next-line no-shadow fetchUpstreamList().then(({ data }) => { - setUpstreams([{ name: formatMessage({ id: 'route.request.override.input' }), id: null }, ...data]); + setUpstreams([ + { name: formatMessage({ id: 'route.request.override.input' }), id: null }, + ...data, + ]); if (step2Data.upstream_id) { onChange({ upstream_id: step2Data.upstream_id }); } @@ -53,8 +56,14 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) required key={field.key} {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)} - label={index === 0 ? formatMessage({ id: 'route.request.override.domain.name.or.ip' }) : ''} - extra={index === 0 ? formatMessage({ id: 'route.request.override.use.domain.name.default.analysis' }) : ''} + label={ + index === 0 ? formatMessage({ id: 'route.request.override.domain.name.or.ip' }) : '' + } + extra={ + index === 0 + ? formatMessage({ id: 'route.request.override.use.domain.name.default.analysis' }) + : '' + } > @@ -62,7 +71,10 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) style={{ marginBottom: 0 }} name={[field.name, 'host']} rules={[ - { required: true, message: formatMessage({ id: 'route.request.override.input.domain.or.ip' }) }, + { + required: true, + message: formatMessage({ id: 'route.request.override.input.domain.or.ip' }), + }, { pattern: new RegExp( /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/, @@ -72,14 +84,24 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) }, ]} > - + = ({ data, form, disabled, onChange }) = ({ data, form, disabled, onChange }) ); const renderTimeUnit = () => ms; - return ( = ({ data, form, disabled, onChange }) { @@ -162,28 +193,56 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) HTTPS - + { - onChange({ upstreamPath: e.target.value === 'keep' ? undefined : '' }); + onChange({ rewriteType: e.target.value }); }} disabled={disabled} > {formatMessage({ id: 'route.request.override.stay.same' })} - {formatMessage({ id: 'route.request.override.edit' })} + {formatMessage({ id: 'page.route.radio.static' })} + {formatMessage({ id: 'page.route.radio.regx' })} - {step2Data.upstreamPath !== undefined && ( + {step2Data.rewriteType === 'regx' && ( + + + + )} + {(step2Data.rewriteType === 'static' || step2Data.rewriteType === 'regx') && ( - + )} - + {renderUpstreamMeta()} - + @@ -214,7 +281,12 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) @@ -224,7 +296,12 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) diff --git a/src/pages/Route/constants.ts b/src/pages/Route/constants.ts index 97e602cefb..bca220b59f 100644 --- a/src/pages/Route/constants.ts +++ b/src/pages/Route/constants.ts @@ -60,6 +60,8 @@ export const DEFAULT_STEP_2_DATA: RouteModule.Step2Data = { upstreamHostList: [{} as RouteModule.UpstreamHost], upstreamHeaderList: [], upstreamPath: undefined, + mappingStrategy: undefined, + rewriteType: 'keep', timeout: { connect: 6000, send: 6000, diff --git a/src/pages/Route/locales/en-US.ts b/src/pages/Route/locales/en-US.ts index e0c3b30e81..78baa5fd50 100644 --- a/src/pages/Route/locales/en-US.ts +++ b/src/pages/Route/locales/en-US.ts @@ -157,4 +157,7 @@ export default { 'route.list': 'Route List', 'route.list.input': 'Please input', 'route.list.create': 'Create', + 'page.route.radio.static': 'Static', + 'page.route.radio.regx': 'Regx', + 'page.route.form.itemLabel.from': 'From', }; diff --git a/src/pages/Route/locales/zh-CN.ts b/src/pages/Route/locales/zh-CN.ts index 0c67f4fc98..5894354245 100644 --- a/src/pages/Route/locales/zh-CN.ts +++ b/src/pages/Route/locales/zh-CN.ts @@ -152,4 +152,7 @@ export default { 'route.list': '路由列表', 'route.list.input': '请输入', 'route.list.create': '创建', + 'page.route.radio.static': '静态重写', + 'page.route.radio.regx': '正则重写', + 'page.route.form.itemLabel.from': '原路径', }; diff --git a/src/pages/Route/transform.ts b/src/pages/Route/transform.ts index 26b292c39c..5c2730238b 100644 --- a/src/pages/Route/transform.ts +++ b/src/pages/Route/transform.ts @@ -81,6 +81,13 @@ export const transformStepData = ({ data.upstream_path = { to: step2Data.upstreamPath, }; + if (step2Data.mappingStrategy) { + data.upstream_path = { + ...data.upstream_path, + from: step2Data.mappingStrategy, + type: 'regx', + }; + } } if (step3Data.plugins.prometheus) { @@ -95,6 +102,8 @@ export const transformStepData = ({ 'advancedMatchingRules', 'upstreamHostList', 'upstreamPath', + 'rewriteType', + 'mappingStrategy', 'upstreamHeaderList', 'websocket', 'timeout', @@ -169,6 +178,14 @@ export const transformRouteData = (data: RouteModule.Body) => { upstream_protocol = 'keep', upstream_id, } = data; + let rewriteType = 'keep'; + if (upstream_path && upstream_path.to) { + if (upstream_path.from) { + rewriteType = 'regx'; + } else { + rewriteType = 'static'; + } + } const upstreamHeaderList = Object.entries(upstream_header || {}).map(([k, v]) => { return { @@ -185,6 +202,8 @@ export const transformRouteData = (data: RouteModule.Body) => { upstreamHostList: transformUpstreamNodes(upstream?.nodes), upstream_id, upstreamPath: upstream_path?.to, + mappingStrategy: upstream_path?.from, + rewriteType, timeout: upstream?.timeout || { connect: 6000, send: 6000, diff --git a/src/pages/Route/typing.d.ts b/src/pages/Route/typing.d.ts index c8ec042bb3..c766120e63 100644 --- a/src/pages/Route/typing.d.ts +++ b/src/pages/Route/typing.d.ts @@ -85,6 +85,8 @@ declare namespace RouteModule { type Step2Data = { upstream_protocol: 'http' | 'https' | 'keep'; upstreamHostList: UpstreamHost[]; + mappingStrategy: string | undefined; + rewriteType: string | undefined; upstreamPath: string | undefined; upstreamHeaderList: UpstreamHeader[]; upstream_id?: string; @@ -127,6 +129,7 @@ declare namespace RouteModule { }; }; upstream_path?: { + type?: string; from?: string; to: string; };