Commit 1d49990e authored by 张烨's avatar 张烨

refactor: 抽取代理设置逻辑和接口权限过期处理

parent 7ef8e4bf
......@@ -2,8 +2,7 @@ const path = require('path');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const { createProxyMiddleware } = require('http-proxy-middleware');
const logger = require('../logger');
const { addProxyMiddleware } = require('../proxy');
function createWebpackMiddleware(compiler, publicPath) {
return webpackDevMiddleware(compiler, {
......@@ -14,116 +13,6 @@ function createWebpackMiddleware(compiler, publicPath) {
});
}
const setupProxyFeature = (app, webpackConfig) => {
console.log(webpackConfig);
if (!Array.isArray(webpackConfig.proxy)) {
if (Object.prototype.hasOwnProperty.call(webpackConfig.proxy, 'target')) {
webpackConfig.proxy = [webpackConfig.proxy];
} else {
webpackConfig.proxy = Object.keys(webpackConfig.proxy).map(context => {
let proxyOptions;
// For backwards compatibility reasons.
const correctedContext = context
.replace(/^\*$/, '**')
.replace(/\/\*$/, '');
if (typeof webpackConfig.proxy[context] === 'string') {
proxyOptions = {
context: correctedContext,
target: webpackConfig.proxy[context],
};
} else {
proxyOptions = Object.assign({}, webpackConfig.proxy[context]);
proxyOptions.context = correctedContext;
}
proxyOptions.logLevel = proxyOptions.logLevel || 'warn';
return proxyOptions;
});
}
}
// eslint-disable-next-line consistent-return
const getProxyMiddleware = proxyConfig => {
const context = proxyConfig.context || proxyConfig.path;
// It is possible to use the `bypass` method without a `target`.
// However, the proxy middleware has no use in this case, and will fail to instantiate.
if (proxyConfig.target) {
return createProxyMiddleware(context, proxyConfig);
}
};
/**
* Assume a proxy configuration specified as:
* proxy: [
* {
* context: ...,
* ...options...
* },
* // or:
* function() {
* return {
* context: ...,
* ...options...
* };
* }
* ]
*/
webpackConfig.proxy.forEach(proxyConfigOrCallback => {
let proxyMiddleware;
let proxyConfig =
typeof proxyConfigOrCallback === 'function'
? proxyConfigOrCallback()
: proxyConfigOrCallback;
proxyMiddleware = getProxyMiddleware(proxyConfig);
if (proxyConfig.ws) {
this.websocketProxies.push(proxyMiddleware);
}
// eslint-disable-next-line consistent-return
const handle = (req, res, next) => {
if (typeof proxyConfigOrCallback === 'function') {
const newProxyConfig = proxyConfigOrCallback();
if (newProxyConfig !== proxyConfig) {
proxyConfig = newProxyConfig;
proxyMiddleware = getProxyMiddleware(proxyConfig);
}
}
// - Check if we have a bypass function defined
// - In case the bypass function is defined we'll retrieve the
// bypassUrl from it otherwise bypassUrl would be null
const isByPassFuncDefined = typeof proxyConfig.bypass === 'function';
const bypassUrl = isByPassFuncDefined
? proxyConfig.bypass(req, res, proxyConfig)
: null;
if (typeof bypassUrl === 'boolean') {
// skip the proxy
req.url = null;
next();
} else if (typeof bypassUrl === 'string') {
// byPass to that url
req.url = bypassUrl;
next();
} else if (proxyMiddleware) {
return proxyMiddleware(req, res, next);
} else {
next();
}
};
app.use(handle);
// Also forward error requests to the proxy so it can handle them.
app.use((error, req, res, next) => handle(req, res, next));
});
};
module.exports = function addDevMiddlewares(app, webpackConfig) {
const compiler = webpack(webpackConfig);
const middleware = createWebpackMiddleware(
......@@ -133,24 +22,10 @@ module.exports = function addDevMiddlewares(app, webpackConfig) {
app.use(middleware);
app.use(webpackHotMiddleware(compiler));
addProxyMiddleware(app);
// Since webpackDevMiddleware uses memory-fs internally to store build
// artifacts, we use it instead
const fs = middleware.fileSystem;
if (process.env.PROXY) {
const proxies = process.env.PROXY.split(';');
// 设置代理
setupProxyFeature(app, {
proxy: proxies.map(proxyStr => {
const mathes = proxyStr.match(/^\s*([/\w]+)\s*:\s*(.+)\s*$/);
return {
path: mathes[1],
target: mathes[2],
changeOrigin: true,
};
}),
});
}
app.get('*', (_req, res) => {
fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => {
......
const { createProxyMiddleware } = require('http-proxy-middleware');
const logger = require('./logger');
const setupProxyFeature = (app, webpackConfig) => {
if (!Array.isArray(webpackConfig.proxy)) {
if (Object.prototype.hasOwnProperty.call(webpackConfig.proxy, 'target')) {
webpackConfig.proxy = [webpackConfig.proxy];
} else {
webpackConfig.proxy = Object.keys(webpackConfig.proxy).map(context => {
let proxyOptions;
// For backwards compatibility reasons.
const correctedContext = context
.replace(/^\*$/, '**')
.replace(/\/\*$/, '');
if (typeof webpackConfig.proxy[context] === 'string') {
proxyOptions = {
context: correctedContext,
target: webpackConfig.proxy[context],
};
} else {
proxyOptions = Object.assign({}, webpackConfig.proxy[context]);
proxyOptions.context = correctedContext;
}
proxyOptions.logLevel = proxyOptions.logLevel || 'warn';
return proxyOptions;
});
}
}
// eslint-disable-next-line consistent-return
const getProxyMiddleware = proxyConfig => {
const context = proxyConfig.context || proxyConfig.path;
// It is possible to use the `bypass` method without a `target`.
// However, the proxy middleware has no use in this case, and will fail to instantiate.
if (proxyConfig.target) {
return createProxyMiddleware(context, proxyConfig);
}
};
/**
* Assume a proxy configuration specified as:
* proxy: [
* {
* context: ...,
* ...options...
* },
* // or:
* function() {
* return {
* context: ...,
* ...options...
* };
* }
* ]
*/
webpackConfig.proxy.forEach(proxyConfigOrCallback => {
let proxyMiddleware;
let proxyConfig =
typeof proxyConfigOrCallback === 'function'
? proxyConfigOrCallback()
: proxyConfigOrCallback;
proxyMiddleware = getProxyMiddleware(proxyConfig);
if (proxyConfig.ws) {
this.websocketProxies.push(proxyMiddleware);
}
// eslint-disable-next-line consistent-return
const handle = (req, res, next) => {
if (typeof proxyConfigOrCallback === 'function') {
const newProxyConfig = proxyConfigOrCallback();
if (newProxyConfig !== proxyConfig) {
proxyConfig = newProxyConfig;
proxyMiddleware = getProxyMiddleware(proxyConfig);
}
}
// - Check if we have a bypass function defined
// - In case the bypass function is defined we'll retrieve the
// bypassUrl from it otherwise bypassUrl would be null
const isByPassFuncDefined = typeof proxyConfig.bypass === 'function';
const bypassUrl = isByPassFuncDefined
? proxyConfig.bypass(req, res, proxyConfig)
: null;
if (typeof bypassUrl === 'boolean') {
// skip the proxy
req.url = null;
next();
} else if (typeof bypassUrl === 'string') {
// byPass to that url
req.url = bypassUrl;
next();
} else if (proxyMiddleware) {
return proxyMiddleware(req, res, next);
} else {
next();
}
};
app.use(handle);
// Also forward error requests to the proxy so it can handle them.
app.use((error, req, res, next) => handle(req, res, next));
});
};
const addProxyMiddleware = app => {
if (process.env.PROXY) {
const proxies = process.env.PROXY.split(';');
// 设置代理
setupProxyFeature(app, {
proxy: proxies.map(proxyStr => {
const mathes = proxyStr.match(/^\s*([/\w]+)\s*:\s*(.+)\s*$/);
return {
path: mathes[1],
target: mathes[2],
changeOrigin: true,
};
}),
});
}
};
module.exports = {
addProxyMiddleware,
};
import { notification, message as amessage } from 'antd';
import { notification, message as amessage, Button } from 'antd';
import isUndefined from 'lodash/isUndefined';
import React from 'react';
import { BASENAME } from '../constants';
// 1. 业务重定向
const bizRedirectHandler = response => {
const { code, data } = response;
if (Number(code) === 302 && data && data.redirectUrl) {
const { status, data } = response;
if (status === 302 && data && data.redirectUrl) {
window.location.assign(data.redirectUrl);
} else if (status === 401) {
const key = 'authrizeFail';
const btn = (
<Button
type="primary"
size="small"
onClick={() => {
notification.close(key);
window.location.href = `/${BASENAME}/user/login`;
}}
>
确定
</Button>
);
notification.warning({
key,
message: '授权失败,即将跳转到登录页',
duration: 4,
btn,
});
setTimeout(() => {
window.location.href = `/${BASENAME}/user/login`;
}, 4000);
}
};
// 2. 开发级错误信息转换
const bizDevErrorAdapter = response => {
const { code, success, message, description } = response;
const opCode = Number(code);
const { status, success, message, description } = response;
const opCode = Number(status);
if (success === false && opCode >= 300 && opCode !== 302) {
return {
message: message || `${code}`,
message: message || `${status}`,
description: description || message,
};
}
......@@ -24,8 +49,8 @@ const bizDevErrorAdapter = response => {
// 3. 用户级错误信息转换
const bizErrorMessageAdapter = response => {
const { code, success, message } = response;
const opCode = Number(code);
const { status, success, message } = response;
const opCode = Number(status);
if (success === false && (opCode < 300 || opCode === 302)) {
return message;
}
......
......@@ -5,8 +5,10 @@ import toLower from 'lodash/toLower';
// import isArray from 'lodash/isArray';
// import isArrayLikeObject from 'lodash/isArrayLikeObject';
import isFunction from 'lodash/isFunction';
// import extendConfig from './defaultConfig';
const globalConfig = {}
import extendConfig from './defaultConfig';
const globalConfig = {
bizRedirectHandler: extendConfig.bizRedirectHandler
}
const globalConfigMatchers = [];
/* no-unused-vars */
const getMatchedConfig = requestConfig => {
......@@ -36,6 +38,17 @@ axios.interceptors.request.use( function (request){
// Do something with response error
return Promise.reject(error);
})
axios.interceptors.response.use(function (response) {
return response
}, (error) => {
if (error.response) {
switch (error.response.status) {
case 401:
globalConfig.bizRedirectHandler(error.response)
}
}
return Promise.reject(error);
})
export const request = (config, ctx) => {
const {
......@@ -87,7 +100,10 @@ export const request = (config, ctx) => {
requestOptions = bizRequestAdapter(requestOptions);
}
return axios(requestOptions)
return axios(requestOptions).then(r => {
console.log(r)
return r
})
.then(raw => raw && raw.data)
.then(
res =>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment