From a0d7e0ce2269a366e56e5f0a9ca6ecacddd07070 Mon Sep 17 00:00:00 2001 From: litesun <31329157+LiteSun@users.noreply.github.com> Date: Tue, 1 Sep 2020 09:43:01 +0800 Subject: [PATCH] feat: added chash (#429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * merge master (#1) * add: Determine duplicate names api for route & upstream (#305) * fix: transaction in routes and upstreams (#306) * add transaction for ssl and consumer (#308) * update ci/cd for api (#307) * update github actions for api ci cd * fix: working-directory * fix error * fix: step name * fix: mysql config for github action * test * use default config * test: add e2e test for ssl and consumer (#309) * test: add e2e test for ssl and consumer * fix: change assert to avoid the mutual influence of route and service test * remove useless code * Feat: added Route Consumer and Upstream (#304) * feat: added routes * feat: added Consumer * feat: added upstream * feat: update SSL * fix: routes * feat: added commit command * feat(route): set empty array for upstreamHeaderList * fix: e2e test use the same function to set up router (#310) * fix: return all objects when search route & upstream (#311) * fix: route search * fix: upstream search * fix(deploy): added missing yarn.lock * fix: proxy-rewrite plugin in upstream (#312) * fix(SSL): search api * docs: added tips when deployment * feat(Deploy): use node alpine image * fix(Route): set required field for custom redirect * fix(Route): check if redirect is empty object * fix(Deploy): add Python installation in dockerfile (#316) Signed-off-by: imjoey * fix(Route): update desc for status code * fix: proxy-path default type is static (#318) * add proxyRewrite test (#319) * feat: bump dependencies version (#320) * feat(Deploy): update Dockerfile * feat(Deploy): update Deploy Dockerfile * feat(Pages): update pages (#324) * feat(Pages): update pages * chore: update routes * fix(Route): omit upstream_id when not exist * i18n consumer (#325) * i18n ssl (#335) * nationalization PluginPage component (#323) * i18n upstream (#334) * feat(i18n): set module (#336) * i18n set * change set to setting * feat(i18n): metrics module (#326) * i18n metrics * combine import * feat(i18n): route module (#327) * i18n route * combine import * doc: sync config.yaml from the latest version of APISIX (#344) * i18n route (#342) * i18n actionbar (#343) * fix: transform vars error (#347) * feat(i18n): pluginpage component (#345) * i18n pluginpage * change pluginpage to PluginPage * feature: support run in mac system (#349) * combine import (#348) * i18n menu (#351) * i18n PluginPage (#350) * feat: prepare to release (#352) * feat(ManagerAPI): added ASF header * feat(FE): aded ASF Header * feat(FE): added ASF header * fix(FE): update PluginDrawer * feat: remove some images * feat: added LICENSE * feat: update Version * feat: added NOTICE & CODE_OF_CONDUCT * feat: added initial CHANGELOG * feat: rename CODE_OF_CONDUCT * feat: revert version * feat: update LICENSE * feat: update License * feat(conf): update default preview API (#353) * doc: add install doc for manager-api (#355) * doc: add install doc for manager-api * doc: modify folder from build to run * doc: add ASF header * fix(ci): resolve lint failures (#354) * fix(deploy): failed to start manager_api (#363) Signed-off-by: imjoey * feat(i18n): modify some i18n according to the proposal#331 (#366) * Create CONTRIBUTING.md (#368) * Create CONTRIBUTING.md * Create ISSUE_TEMPLATE * Create PULL_REQUEST_TEMPLATE * doc: remove all ‘incubator’ (#367) * feat(deploy): set gen-config-yaml.sh executable (#362) This also would simplify the docs. Signed-off-by: imjoey * feat(i18n): Use auto load i18n (#332) (#371) * Create ci.yml (#372) * feat: release 1.5 (#364) * Feat release 1.5 (#358) * feat(doc): update README * feat: update CHANGELOG * doc: add usage of dashbaord * Revert "doc: add usage of dashbaord" This reverts commit 5a08c7f43539a44cd0cf0f6175574e59efbd0ab6. * feat(Doc): update deployment * feat(Doc): update the deployment * feat(Doc): update the deployment * feat: remove incubator text * doc: modify doc for manager-api runing in local * feat(Doc): update README * doc: check env variables and give run.sh power to execute * feat(Doc): update Deployment * feat(Doc): update deployment * doc: modify manager-api build * feat: update ignore file Co-authored-by: kv Co-authored-by: 琚致远 * feat: cherry-pick 4fd0ce79bb34dbe8c31b7a27884930e3b0e5437c * feat(compose): remove images * feat: added line Co-authored-by: kv Co-authored-by: 琚致远 * feat: Unified access entrance, only the dashboard port is exposed to … (#370) * feat: Unified access entrance, only the dashboard port is exposed to the outside * add EOL * docs: create I18N_USER_GUIDE.md (#373) * docs: create I18N_USER_GUIDE.md * docs: modify I18N_USER_GUIDE.md * feat(Doc): added deploy doc for docker (#376) * feat(Doc): added deploy doc for docker * feat: added CD * feat(Netlify): added proxy * feat: update API * feat: remove console * feat(Netlify): update redirect rule * feat: update README * feat: update README * update go module proxy (#378) * Update README.md (#379) * Update README.md * Update README.md * Create Preview.md * feat(Doc): added snapshots for Preview * feat(Doc): update images * feat(Doc): update images * Update README.md * Update netlify.toml * feat(route): route add params mapping feature (#375) (#377) * feat(doc): update deploy manually doc * fix: mv config.yml to config-default.yml in the latest version of apisix (#383) * fix: wget config-default.yaml the output file need to be named config.yaml (#384) * fix #386 wget special output file use -O (#387) * feat(authentication): create authentication module (#330) * feat(authentication): create module typing definition * feat(authentication): create Login page * feat(authentication): update typing definition * feat(authentication): add centent to Login page * feat(authentication): update typing definition * feat(authentication): update Login page to add Password and Test method * feat(authentication): update typing definition to add check and submit function * feat(authentication): move Test login method to Example * feat(authentication): add check and submit function * feat(authentication): add submit function in Login page * feat(authentication): add test to Password login method * feat(authentication): change example LoginMethod text * feat(authentication): add i18n content * feat(authentication): redirect to index when login success * feat(i18n): update i18n file import remove import i18n file of user module manually and try auto import by umi.js * feat(authentication): create authentication configure items * fix(authentication): fix logging filter write back request body for read by PostForm function * feat(authentication): create authentication controller * feat(authentication): update dependencies * fix(authentication): fix logging filter * feat(authentication): change to session for authentication * feat(authentication): create authentication filter use authentication filter to check every request * feat(authentication): create unit test case * fix(authentication): change HTTP code when authentication fail request * feat(authentication): add jwt dependency * feat(authentication): create session configures * feat(authentication): change cookie-based session to jwt * feat(authentication): change cors Access-Control-Allow-Headers header * feat(authentication): change login page path and error handler * feat(authentication): create request interceptor to add Authorization header * feat(authentication): connect to backend login API and i18n * feat(authentication): create logout page * feat(authentication): add redirect query to back previous page * feat(authentication): update LoginMethod definition for logout * feat(authentication): add logout button * feat(authentication): improve login page * fix: clean codes * fix(authentication): fix unit test crash * feat(authentication): remove API url setting * feat(authentication): improve session check * feat(authentication): redirect to login page when not exist token * fix: clean codes and add ASF header * feat(User): update prefix * fix(ci): fix preview environment (#388) * fix README typo (#389) * fix(ci): fix read configuration file path in docker (#390) * doc: Introducing manager-api (#391) * Update nginx.conf * Update Dockerfile * Revert "Update Dockerfile" This reverts commit ea827bfd2789c2d939a2517b279170cccdadf35b. * fix: preview mysql pwd was wrong (#393) * README in Chinese (#398) * feat(doc): added Chinese version of README * fix(README.zh-CN.md): fix wrong link * fix(README.zh-CN.md): add link to README.md * fix(README.zh-CN.md): sync with README.md * fix(README.zh-CN.md): Fix some translation errors * fix: dashboard /user/login get error code 405 (#397) * fix: fix dashboard /user/login get error code 405 * fix: modify nginx according to giphoo proposal * fix(authentication): change Apache APISIX copyright (#401) * fix: configure only necessary items, such as etcd host (#405) * fix: configure only necessary items, such as etcd host * fix: configure only necessary items, such as etcd host * fix end of line * fix: using default admin key (#408) * fix: we need conf.json when deploying manager-api in local (#409) * fix: we need conf.json when deploying manager-api in loal * fix: log error when starting manager failed * fix: click create ssl prestep not response (#407) * fix: submit setting grafanaURl without validation (#413) * feat: support generate `script` for APISIX (#411) * feat: support generate `script` for APISIX * not run in `/root` dir * add `config.yaml` for APISIX * fix path * fix(authentication): change login api url (#414) * fix(authentication): change manager API login path * fix(authentication): change authentication unit test * fix(authentication): clean nginx.conf codes * fix(authentication): change login URL of front end * fix(authentication): change authentication filter rule Co-authored-by: kv Co-authored-by: nic-chen <33000667+nic-chen@users.noreply.github.com> Co-authored-by: 琚致远 Co-authored-by: juzhiyuan Co-authored-by: Joey Co-authored-by: bzp2010 Co-authored-by: TikWind <65604564+TikWind@users.noreply.github.com> Co-authored-by: Lien Co-authored-by: Rapiz Co-authored-by: liuxiran Co-authored-by: jie Co-authored-by: Rapiz Co-authored-by: 琚致远 Co-authored-by: Tusdasa翼 Co-authored-by: Shuyang Wu Co-authored-by: Baoyuan * feat: added chash * feat: update transform Co-authored-by: kv Co-authored-by: nic-chen <33000667+nic-chen@users.noreply.github.com> Co-authored-by: 琚致远 Co-authored-by: juzhiyuan Co-authored-by: Joey Co-authored-by: bzp2010 Co-authored-by: TikWind <65604564+TikWind@users.noreply.github.com> Co-authored-by: Lien Co-authored-by: Rapiz Co-authored-by: liuxiran Co-authored-by: jie Co-authored-by: Rapiz Co-authored-by: 琚致远 Co-authored-by: Tusdasa翼 Co-authored-by: Shuyang Wu Co-authored-by: Baoyuan --- src/pages/Route/Create.tsx | 2 + .../components/Step2/RequestRewriteView.tsx | 263 ++++++++++-------- src/pages/Route/constants.ts | 16 ++ src/pages/Route/transform.ts | 12 +- src/pages/Route/typing.d.ts | 5 + src/pages/Upstream/components/Step1.tsx | 127 +++++++-- src/pages/Upstream/constants.ts | 18 +- 7 files changed, 312 insertions(+), 131 deletions(-) diff --git a/src/pages/Route/Create.tsx b/src/pages/Route/Create.tsx index 326f6675908629..51ee1c042b8107 100644 --- a/src/pages/Route/Create.tsx +++ b/src/pages/Route/Create.tsx @@ -156,7 +156,9 @@ const Page: React.FC = (props) => { ...form2.getFieldsValue(), ...data, }); + setStep2Data({ ...form2.getFieldsValue(), ...params } as RouteModule.Step2Data); }); + return; } setStep2Data({ ...form2.getFieldsValue(), ...params } as RouteModule.Step2Data); }} diff --git a/src/pages/Route/components/Step2/RequestRewriteView.tsx b/src/pages/Route/components/Step2/RequestRewriteView.tsx index 8bb4616feb8e44..da56ef1004e700 100644 --- a/src/pages/Route/components/Step2/RequestRewriteView.tsx +++ b/src/pages/Route/components/Step2/RequestRewriteView.tsx @@ -21,7 +21,12 @@ import { Input, Row, Col, InputNumber, Button, Select } from 'antd'; import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons'; import { useIntl } from 'umi'; -import { FORM_ITEM_LAYOUT, FORM_ITEM_WITHOUT_LABEL } from '@/pages/Route/constants'; +import { + FORM_ITEM_LAYOUT, + FORM_ITEM_WITHOUT_LABEL, + HASH_KEY_LIST, + HASH_ON_LIST, +} from '@/pages/Route/constants'; import PanelSection from '@/components/PanelSection'; import styles from '../../Create.less'; import { fetchUpstreamList } from '../../service'; @@ -48,117 +53,157 @@ const RequestRewriteView: React.FC = ({ data, form, disabled, onChange }) }); }, []); const renderUpstreamMeta = () => ( - - {(fields, { add, remove }) => ( + <> + + + + {step2Data.type === 'chash' && ( <> - {fields.map((field, index) => ( - - - - - - - - - - - - - - - - - - - {!upstreamDisabled && - (fields.length > 1 ? ( - { - remove(field.name); - }} - /> - ) : null)} - - - - ))} - {!upstreamDisabled && ( - - - - )} + + + + + + )} - + + {(fields, { add, remove }) => ( + <> + {fields.map((field, index) => ( + + + + + + + + + + + + + + + + + + + {!upstreamDisabled && + (fields.length > 1 ? ( + { + remove(field.name); + }} + /> + ) : null)} + + + + ))} + {!upstreamDisabled && ( + + + + )} + + )} + + ); const renderTimeUnit = () => ms; diff --git a/src/pages/Route/constants.ts b/src/pages/Route/constants.ts index 435dbe92e86f0d..0620bbd8beeec9 100644 --- a/src/pages/Route/constants.ts +++ b/src/pages/Route/constants.ts @@ -60,6 +60,7 @@ export const DEFAULT_STEP_2_DATA: RouteModule.Step2Data = { upstreamHostList: [{} as RouteModule.UpstreamHost], upstreamHeaderList: [], upstreamPath: undefined, + type: 'roundrobin', mappingStrategy: undefined, rewriteType: 'keep', timeout: { @@ -82,3 +83,18 @@ export const INIT_CHART = { selected: {}, hovered: {}, }; + +export const HASH_KEY_LIST = [ + 'remote_addr', + 'host', + 'uri', + 'server_name', + 'server_addr', + 'request_uri', + 'query_string', + 'remote_port', + 'hostname', + 'arg_id', +]; + +export const HASH_ON_LIST = ['vars', 'header', 'cookie', 'consumer']; diff --git a/src/pages/Route/transform.ts b/src/pages/Route/transform.ts index 02ce6dedc8b26d..dae7d91edb3051 100644 --- a/src/pages/Route/transform.ts +++ b/src/pages/Route/transform.ts @@ -30,6 +30,12 @@ export const transformStepData = ({ upstream_header[header.header_name] = header.header_value || ''; }); + const chashData: any = {}; + if (step2Data.type === 'chash') { + chashData.key = step2Data.key; + chashData.hash_on = step2Data.hash_on; + } + let redirect: RouteModule.Redirect = {}; if (step1Data.redirectOption === 'disabled') { redirect = {}; @@ -70,7 +76,8 @@ export const transformStepData = ({ return [key, operator, value]; }), upstream: { - type: 'roundrobin', + type: step2Data.type, + ...chashData, nodes, timeout: step2Data.timeout, }, @@ -199,6 +206,9 @@ export const transformRouteData = (data: RouteModule.Body) => { const step2Data: RouteModule.Step2Data = { upstream_protocol, upstreamHeaderList, + type: upstream ? upstream.type : 'roundrobin', + hash_on: upstream ? upstream.hash_on : undefined, + key: upstream ? upstream.key : undefined, upstreamHostList: transformUpstreamNodes(upstream?.nodes), upstream_id, upstreamPath: upstream_path?.to, diff --git a/src/pages/Route/typing.d.ts b/src/pages/Route/typing.d.ts index 56d4e7a7d489fc..9fc25dc6b62004 100644 --- a/src/pages/Route/typing.d.ts +++ b/src/pages/Route/typing.d.ts @@ -86,6 +86,9 @@ declare namespace RouteModule { type Step2Data = { upstream_protocol: 'http' | 'https' | 'keep'; + type: 'roundrobin' | 'chash'; + hash_on?: string; + key?: string; upstreamHostList: UpstreamHost[]; mappingStrategy: string | undefined; rewriteType: string | undefined; @@ -121,6 +124,8 @@ declare namespace RouteModule { vars: [string, Operator, string][]; upstream: { type: 'roundrobin' | 'chash'; + hash_on?: string; + key?: string; nodes: { [key: string]: number; }; diff --git a/src/pages/Upstream/components/Step1.tsx b/src/pages/Upstream/components/Step1.tsx index 9ac7f733909934..cfbf2b433d0f87 100644 --- a/src/pages/Upstream/components/Step1.tsx +++ b/src/pages/Upstream/components/Step1.tsx @@ -21,7 +21,12 @@ import { useIntl } from 'umi'; import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import Button from 'antd/es/button'; -import { FORM_ITEM_WITHOUT_LABEL, FORM_ITEM_LAYOUT } from '@/pages/Upstream/constants'; +import { + FORM_ITEM_WITHOUT_LABEL, + FORM_ITEM_LAYOUT, + HASH_KEY_LIST, + HASH_ON_LIST, +} from '@/pages/Upstream/constants'; type Props = { form: FormInstance; @@ -41,7 +46,6 @@ const initialValues = { }; const Step1: React.FC = ({ form, disabled }) => { - const { formatMessage } = useIntl(); const renderUpstreamMeta = () => ( @@ -53,7 +57,11 @@ const Step1: React.FC = ({ form, disabled }) => { required key={field.key} {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)} - label={index === 0 ? formatMessage({ id: 'upstream.step.backend.server.domain.or.ip' }) : ''} + label={ + index === 0 + ? formatMessage({ id: 'upstream.step.backend.server.domain.or.ip' }) + : '' + } extra={ index === 0 ? formatMessage({ id: 'upstream.step.domain.name.default.analysis' }) @@ -66,7 +74,10 @@ const Step1: React.FC = ({ form, disabled }) => { style={{ marginBottom: 0 }} name={[field.name, 'host']} rules={[ - { required: true, message: formatMessage({ id: 'upstream.step.input.domain.name.or.ip' }) }, + { + required: true, + message: formatMessage({ id: 'upstream.step.input.domain.name.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,}$)/, @@ -76,25 +87,48 @@ const Step1: React.FC = ({ form, disabled }) => { }, ]} > - + - + - + = ({ form, disabled }) => { add(); }} > - {formatMessage({ id: 'upstream.step.create' })} + + {formatMessage({ id: 'upstream.step.create' })} )} @@ -138,24 +173,73 @@ const Step1: React.FC = ({ form, disabled }) => { return (
- - + + - + - + + + {() => { + if (form.getFieldValue('type') === 'chash') { + return ( + <> + + + + + + + + ); + } + return null; + }} + {renderUpstreamMeta()} @@ -165,7 +249,9 @@ const Step1: React.FC = ({ form, disabled }) => { @@ -175,7 +261,12 @@ const Step1: React.FC = ({ form, disabled }) => { diff --git a/src/pages/Upstream/constants.ts b/src/pages/Upstream/constants.ts index 25bb12f92c7cc7..c9e2306e125edf 100644 --- a/src/pages/Upstream/constants.ts +++ b/src/pages/Upstream/constants.ts @@ -18,9 +18,6 @@ export const FORM_ITEM_LAYOUT = { labelCol: { span: 6, }, - wrapperCol: { - span: 18, - }, }; export const FORM_ITEM_WITHOUT_LABEL = { @@ -29,3 +26,18 @@ export const FORM_ITEM_WITHOUT_LABEL = { sm: { span: 20, offset: 6 }, }, }; + +export const HASH_KEY_LIST = [ + 'remote_addr', + 'host', + 'uri', + 'server_name', + 'server_addr', + 'request_uri', + 'query_string', + 'remote_port', + 'hostname', + 'arg_id', +]; + +export const HASH_ON_LIST = ['vars', 'header', 'cookie', 'consumer'];