You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/08/17 09:19:29 UTC
[apisix-dashboard] branch master updated: feat(route): route add
params mapping feature (#375) (#377)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan 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 585830f feat(route): route add params mapping feature (#375) (#377)
585830f is described below
commit 585830f18b1a347b4df45b9f7e02b5fff2b73b7e
Author: liuxiran <be...@126.com>
AuthorDate: Mon Aug 17 17:19:22 2020 +0800
feat(route): route add params mapping feature (#375) (#377)
---
.../Route/components/Step1/MatchingRulesView.tsx | 2 +-
.../components/Step2/HttpHeaderRewriteView.tsx | 31 ++++--
.../Route/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 f6284d4..be403da 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<Props> = ({ data, disabled, onChange }) => {
cancelText={formatMessage({ id: 'route.match.cancel' })}
destroyOnClose
>
- <Form form={modalForm} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}>
+ <Form form={modalForm} labelCol={{ span: 9 }} wrapperCol={{ span: 15 }}>
<Form.Item
label={formatMessage({ id: 'route.match.parameter.position' })}
name="position"
diff --git a/src/pages/Route/components/Step2/HttpHeaderRewriteView.tsx b/src/pages/Route/components/Step2/HttpHeaderRewriteView.tsx
index 420a7a2..665bb21 100644
--- a/src/pages/Route/components/Step2/HttpHeaderRewriteView.tsx
+++ b/src/pages/Route/components/Step2/HttpHeaderRewriteView.tsx
@@ -51,7 +51,9 @@ const HttpHeaderRewriteView: React.FC<Props> = ({ 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<Props> = ({ data, disabled, onChange }) =>
return (
<Modal
- title={mode === 'EDIT' ? formatMessage({ id: 'route.http.edit.request.header' }) : formatMessage({ id: 'route.http.operate.request.header' })}
+ title={
+ mode === 'EDIT'
+ ? formatMessage({ id: 'route.http.edit.request.header' })
+ : formatMessage({ id: 'route.http.operate.request.header' })
+ }
centered
visible
onOk={handleOk}
@@ -126,22 +132,33 @@ const HttpHeaderRewriteView: React.FC<Props> = ({ data, disabled, onChange }) =>
cancelText={formatMessage({ id: 'route.http.cancel' })}
destroyOnClose
>
- <Form form={modalForm} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}>
+ <Form form={modalForm} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
<Form.Item
label={formatMessage({ id: 'route.http.request.header.name' })}
name="header_name"
- rules={[{ required: true, message: formatMessage({ id: 'route.http.input.request.header.name' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.http.input.request.header.name' }),
+ },
+ ]}
>
<Input />
</Form.Item>
<Form.Item
label={formatMessage({ id: 'route.http.action' })}
name="header_action"
- rules={[{ required: true, message: formatMessage({ id: 'route.http.select.actions' }) }]}
+ rules={[
+ { required: true, message: formatMessage({ id: 'route.http.select.actions' }) },
+ ]}
>
<Select onChange={(e) => setShowModalValue(e === 'override')}>
- <Select.Option value="override">{formatMessage({ id: 'route.http.override.or.create' })}</Select.Option>
- <Select.Option value="remove">{formatMessage({ id: 'route.http.delete' })}</Select.Option>
+ <Select.Option value="override">
+ {formatMessage({ id: 'route.http.override.or.create' })}
+ </Select.Option>
+ <Select.Option value="remove">
+ {formatMessage({ id: 'route.http.delete' })}
+ </Select.Option>
</Select>
</Form.Item>
{showModalValue && (
diff --git a/src/pages/Route/components/Step2/RequestRewriteView.tsx b/src/pages/Route/components/Step2/RequestRewriteView.tsx
index 337c810..8bb4616 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<Props> = ({ 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<Props> = ({ 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' })
+ : ''
+ }
>
<Row style={{ marginBottom: '10px' }} gutter={16}>
<Col span={9}>
@@ -62,7 +71,10 @@ const RequestRewriteView: React.FC<Props> = ({ 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<Props> = ({ data, form, disabled, onChange })
},
]}
>
- <Input placeholder={formatMessage({ id: 'route.request.override.domain.name.or.ip' })} disabled={upstreamDisabled} />
+ <Input
+ placeholder={formatMessage({
+ id: 'route.request.override.domain.name.or.ip',
+ })}
+ disabled={upstreamDisabled}
+ />
</Form.Item>
</Col>
<Col span={4}>
<Form.Item
style={{ marginBottom: 0 }}
name={[field.name, 'port']}
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.input.port.number' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.input.port.number' }),
+ },
+ ]}
>
<InputNumber
placeholder={formatMessage({ id: 'route.request.override.port.number' })}
@@ -93,7 +115,12 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
<Form.Item
style={{ marginBottom: 0 }}
name={[field.name, 'weight']}
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.input.weight' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.input.weight' }),
+ },
+ ]}
>
<InputNumber
placeholder={formatMessage({ id: 'route.request.override.weight' })}
@@ -135,7 +162,6 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
);
const renderTimeUnit = () => <span style={{ margin: '0 8px' }}>ms</span>;
-
return (
<PanelSection title={formatMessage({ id: 'route.request.override' })}>
<Form
@@ -148,7 +174,12 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
<Form.Item
label={formatMessage({ id: 'route.request.override.protocol' })}
name="upstream_protocol"
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.select.protocol' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.select.protocol' }),
+ },
+ ]}
>
<Radio.Group
onChange={(e) => {
@@ -162,28 +193,56 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
<Radio value="https">HTTPS</Radio>
</Radio.Group>
</Form.Item>
- <Form.Item label={formatMessage({ id: 'route.request.override.path' })}>
+ <Form.Item label={formatMessage({ id: 'route.request.override.path' })} name="rewriteType">
<Radio.Group
- defaultValue={step2Data.upstreamPath === undefined ? 'keep' : 'modify'}
onChange={(e) => {
- onChange({ upstreamPath: e.target.value === 'keep' ? undefined : '' });
+ onChange({ rewriteType: e.target.value });
}}
disabled={disabled}
>
<Radio value="keep">{formatMessage({ id: 'route.request.override.stay.same' })}</Radio>
- <Radio value="modify">{formatMessage({ id: 'route.request.override.edit' })}</Radio>
+ <Radio value="static">{formatMessage({ id: 'page.route.radio.static' })}</Radio>
+ <Radio value="regx">{formatMessage({ id: 'page.route.radio.regx' })}</Radio>
</Radio.Group>
</Form.Item>
- {step2Data.upstreamPath !== undefined && (
+ {step2Data.rewriteType === 'regx' && (
+ <Form.Item
+ label={formatMessage({ id: 'page.route.form.itemLabel.from' })}
+ name="mappingStrategy"
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.input.path' }),
+ },
+ ]}
+ >
+ <Input
+ disabled={disabled}
+ placeholder={formatMessage({ id: 'route.request.override.path.example' })}
+ />
+ </Form.Item>
+ )}
+ {(step2Data.rewriteType === 'static' || step2Data.rewriteType === 'regx') && (
<Form.Item
label={formatMessage({ id: 'route.request.override.new.path' })}
name="upstreamPath"
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.input.path' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.input.path' }),
+ },
+ ]}
>
- <Input disabled={disabled} placeholder={formatMessage({ id: 'route.request.override.path.example' })} />
+ <Input
+ disabled={disabled}
+ placeholder={formatMessage({ id: 'route.request.override.path.example' })}
+ />
</Form.Item>
)}
- <Form.Item label={formatMessage({ id: 'route.request.override.upstream' })} name="upstream_id">
+ <Form.Item
+ label={formatMessage({ id: 'route.request.override.upstream' })}
+ name="upstream_id"
+ >
<Select
onChange={(value) => {
onChange({ upstream_id: value });
@@ -200,11 +259,19 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
</Select>
</Form.Item>
{renderUpstreamMeta()}
- <Form.Item label={formatMessage({ id: 'route.request.override.connection.timeout' })} required>
+ <Form.Item
+ label={formatMessage({ id: 'route.request.override.connection.timeout' })}
+ required
+ >
<Form.Item
name={['timeout', 'connect']}
noStyle
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.input.connection.timeout' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.input.connection.timeout' }),
+ },
+ ]}
>
<InputNumber disabled={upstreamDisabled} />
</Form.Item>
@@ -214,7 +281,12 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
<Form.Item
name={['timeout', 'send']}
noStyle
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.inout.send.timeout' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.inout.send.timeout' }),
+ },
+ ]}
>
<InputNumber disabled={upstreamDisabled} />
</Form.Item>
@@ -224,7 +296,12 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange })
<Form.Item
name={['timeout', 'read']}
noStyle
- rules={[{ required: true, message: formatMessage({ id: 'route.request.override.inout.receive.timeout' }) }]}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'route.request.override.inout.receive.timeout' }),
+ },
+ ]}
>
<InputNumber disabled={upstreamDisabled} />
</Form.Item>
diff --git a/src/pages/Route/constants.ts b/src/pages/Route/constants.ts
index 97e602c..bca220b 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 e0c3b30..78baa5f 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 0c67f4f..5894354 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 26b292c..5c27302 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 c8ec042..c766120 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;
};