You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by su...@apache.org on 2020/11/27 06:38:02 UTC

[apisix-dashboard] branch master updated: feat: add remote_addrs in route step1 page (#891)

This is an automated email from the ASF dual-hosted git repository.

sunyi 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 707255c  feat: add remote_addrs in route step1 page (#891)
707255c is described below

commit 707255c3528cb913f21958da97dc74ac95ecc34b
Author: litesun <su...@apache.org>
AuthorDate: Fri Nov 27 14:37:54 2020 +0800

    feat: add remote_addrs in route step1 page (#891)
    
    * feat: add remote_addrs
    
    * feat: update remote_addrs regex
    
    * fix: typo
    
    * feat: Code optimization
---
 .../Route/components/Step1/RequestConfigView.tsx   | 86 ++++++++++++++++++++--
 web/src/pages/Route/constants.ts                   |  1 +
 web/src/pages/Route/locales/en-US.ts               |  5 ++
 web/src/pages/Route/locales/zh-CN.ts               |  5 ++
 web/src/pages/Route/transform.ts                   | 17 ++++-
 web/src/pages/Route/typing.d.ts                    |  2 +
 6 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/web/src/pages/Route/components/Step1/RequestConfigView.tsx b/web/src/pages/Route/components/Step1/RequestConfigView.tsx
index 69ae614..0d41815 100644
--- a/web/src/pages/Route/components/Step1/RequestConfigView.tsx
+++ b/web/src/pages/Route/components/Step1/RequestConfigView.tsx
@@ -30,7 +30,7 @@ import {
 const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
   form,
   disabled,
-  onChange = () => {},
+  onChange = () => { },
 }) => {
   const { formatMessage } = useIntl();
   const HostList = () => (
@@ -41,12 +41,10 @@ const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
             {fields.map((field, index) => (
               <Form.Item
                 {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
-                label={index === 0 ? formatMessage({ id: 'page.route.domainName' }) : ''}
+                label={index === 0 && formatMessage({ id: 'page.route.domainName' })}
                 key={field.key}
                 extra={
-                  index === 0
-                    ? formatMessage({ id: 'page.route.form.itemExtraMessage.domain' })
-                    : ''
+                  index === 0 && formatMessage({ id: 'page.route.form.itemExtraMessage.domain' })
                 }
               >
                 <Form.Item
@@ -107,17 +105,17 @@ const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
             {fields.map((field, index) => (
               <Form.Item
                 {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
-                label={index === 0 ? formatMessage({ id: 'page.route.path' }) : ''}
+                label={index === 0 && formatMessage({ id: 'page.route.path' })}
                 required
                 key={field.key}
                 extra={
-                  index === 0 ? (
+                  index === 0 && (
                     <div>
                       {formatMessage({ id: 'page.route.form.itemExtraMessage1.path' })}
                       <br />
                       {formatMessage({ id: 'page.route.form.itemExtraMessage2.path' })}
                     </div>
-                  ) : null
+                  )
                 }
               >
                 <Form.Item
@@ -177,12 +175,84 @@ const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({
     </Form.List>
   );
 
+  const RemoteAddrList = () => (
+    <Form.List name="remote_addrs">
+      {(fields, { add, remove }) => {
+        return (
+          <div>
+            {fields.map((field, index) => (
+              <Form.Item
+                {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
+                label={index === 0 && formatMessage({ id: 'page.route.remoteAddrs' })}
+                key={field.key}
+                extra={
+                  index === 0 && (
+                    <div>
+                      {formatMessage({ id: 'page.route.form.itemExtraMessage1.remoteAddrs' })}
+                    </div>
+                  )
+                }
+              >
+                <Form.Item
+                  {...field}
+                  validateTrigger={['onChange', 'onBlur']}
+                  rules={[
+                    {
+                      pattern: new RegExp(
+                        /^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$|^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\/[0-9]{1,2}$|^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?$|^([a-fA-F0-9]{0,4}:){0,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$/,
+                        'g',
+                      ),
+                      message: formatMessage({
+                        id: 'page.route.form.itemRulesPatternMessage.remoteAddrs',
+                      }),
+                    },
+                  ]}
+                  noStyle
+                >
+                  <Input
+                    placeholder={`${formatMessage({
+                      id: 'component.global.pleaseEnter',
+                    })} ${formatMessage({ id: 'page.route.remoteAddrs' })}`}
+                    style={{ width: '60%' }}
+                    disabled={disabled}
+                  />
+                </Form.Item>
+                {!disabled && fields.length > 1 && (
+                  <MinusCircleOutlined
+                    className="dynamic-delete-button"
+                    style={{ margin: '0 8px' }}
+                    onClick={() => {
+                      remove(field.name);
+                    }}
+                  />
+                )}
+              </Form.Item>
+            ))}
+            {!disabled && (
+              <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
+                <Button
+                  type="dashed"
+                  onClick={() => {
+                    add();
+                  }}
+                >
+                  <PlusOutlined /> {formatMessage({ id: 'component.global.create' })}
+                </Button>
+              </Form.Item>
+            )}
+          </div>
+        );
+      }}
+    </Form.List>
+  );
+
   return (
     <PanelSection
       title={formatMessage({ id: 'page.route.panelSection.title.requestConfigBasicDefine' })}
     >
       <HostList />
       <UriList />
+      <RemoteAddrList />
       <Form.Item
         label={formatMessage({ id: 'page.route.form.itemLabel.httpMethod' })}
         name="methods"
diff --git a/web/src/pages/Route/constants.ts b/web/src/pages/Route/constants.ts
index 56f7162..6ea3ed3 100644
--- a/web/src/pages/Route/constants.ts
+++ b/web/src/pages/Route/constants.ts
@@ -48,6 +48,7 @@ export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = {
   websocket: false,
   hosts: [''],
   uris: ['/*'],
+  remote_addrs: [''],
   redirectOption: 'disabled',
   redirectURI: '',
   ret_code: 302,
diff --git a/web/src/pages/Route/locales/en-US.ts b/web/src/pages/Route/locales/en-US.ts
index 9dcabe5..bd32bd3 100644
--- a/web/src/pages/Route/locales/en-US.ts
+++ b/web/src/pages/Route/locales/en-US.ts
@@ -63,6 +63,10 @@ export default {
     '1. Request path, for example: /foo/index.html, supports request path prefix /foo/* ;',
   'page.route.form.itemExtraMessage2.path': '2. /* represents all paths',
   'page.route.form.itemRulesPatternMessage.path': 'Begin with / , and * can only at the end',
+  'page.route.form.itemRulesPatternMessage.remoteAddrs':
+    'Please enter a valid IP address, for example: 192.168.1.101, 192.168.1.0/24, ::1, fe80::1, fe80::1/64',
+  'page.route.form.itemExtraMessage1.remoteAddrs':
+    'Client IP, for example: 192.168.1.101, 192.168.1.0/24, ::1, fe80::1, fe80::1/64',
 
   'page.route.httpAction': 'Action',
   'page.route.httpOverrideOrCreate': 'Override/Create',
@@ -97,4 +101,5 @@ export default {
 
   'page.route.domainName': 'Domain Name',
   'page.route.path': 'Path',
+  'page.route.remoteAddrs': 'Remote Addrs',
 };
diff --git a/web/src/pages/Route/locales/zh-CN.ts b/web/src/pages/Route/locales/zh-CN.ts
index 9b27ebd..2e9890e 100644
--- a/web/src/pages/Route/locales/zh-CN.ts
+++ b/web/src/pages/Route/locales/zh-CN.ts
@@ -29,6 +29,7 @@ export default {
   'page.route.rule': '规则',
   'page.route.domainName': '域名',
   'page.route.path': '路径',
+  'page.route.remoteAddrs': '客户端地址',
   'page.route.value': '参数值',
   'page.route.protocol': '协议',
   'page.route.httpHeaderName': 'HTTP 请求头名称',
@@ -60,6 +61,10 @@ export default {
     '1. 请求路径,如 /foo/index.html,支持请求路径前缀 /foo/* ;',
   'page.route.form.itemExtraMessage2.path': '2. /* 代表所有路径',
   'page.route.form.itemRulesPatternMessage.path': '以 / 开头,且 * 只能在最后',
+  'page.route.form.itemExtraMessage1.remoteAddrs':
+    '客户端 IP,例如:192.168.1.101,192.168.1.0/24,::1,fe80::1,fe80::1/64',
+  'page.route.form.itemRulesPatternMessage.remoteAddrs':
+    '请输入合法的 IP 地址,例如:192.168.1.101,192.168.1.0/24,::1,fe80::1,fe80::1/64',
 
   // select
   'page.route.select.option.enableHttps': '启用 HTTPS',
diff --git a/web/src/pages/Route/transform.ts b/web/src/pages/Route/transform.ts
index f95e9d9..93c52ab 100644
--- a/web/src/pages/Route/transform.ts
+++ b/web/src/pages/Route/transform.ts
@@ -97,6 +97,7 @@ export const transformStepData = ({
     'redirect',
     'vars',
     'plugins',
+    'remote_addrs',
     form1Data.hosts.filter(Boolean).length !== 0 ? 'hosts' : '',
   ]);
 };
@@ -130,13 +131,27 @@ export const transformUpstreamNodes = (
 };
 
 export const transformRouteData = (data: RouteModule.Body) => {
-  const { name, desc, methods, uris, uri, hosts, host, vars, status, upstream, upstream_id } = data;
+  const {
+    name,
+    desc,
+    methods,
+    uris,
+    uri,
+    hosts,
+    host,
+    remote_addrs,
+    vars,
+    status,
+    upstream,
+    upstream_id,
+  } = data;
   const form1Data: Partial<RouteModule.Form1Data> = {
     name,
     desc,
     status,
     hosts: hosts || (host && [host]) || [''],
     uris: uris || (uri && [uri]) || [],
+    remote_addrs: remote_addrs || [''],
     methods,
   };
 
diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts
index 3dc2864..aec530a 100644
--- a/web/src/pages/Route/typing.d.ts
+++ b/web/src/pages/Route/typing.d.ts
@@ -79,6 +79,7 @@ declare namespace RouteModule {
     uris: string[];
     host?: string;
     hosts: string[];
+    remote_addrs: string[];
     vars: [string, Operator, string][];
     upstream: {
       type: 'roundrobin' | 'chash';
@@ -175,6 +176,7 @@ declare namespace RouteModule {
     websocket: boolean;
     hosts: string[];
     uris: string[];
+    remote_addrs: string[];
     methods: HttpMethod[];
     redirectOption: 'forceHttps' | 'customRedirect' | 'disabled';
     redirectURI?: string;