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, };