Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin-qiankun): 本地研发时支持设置 http-proxy-middleware 参数 & 重定向逻辑改造 #10960

Merged
merged 6 commits into from
Apr 17, 2023
55 changes: 40 additions & 15 deletions packages/plugins/src/qiankun/slave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from '@umijs/bundler-utils/compiled/express';
import {
createProxyMiddleware,
Options,
// @ts-ignore 现在打包好的 http-proxy-middleware 有导出 responseInterceptor,但没有导出声明
responseInterceptor,
} from '@umijs/bundler-utils/compiled/http-proxy-middleware';
Expand Down Expand Up @@ -32,7 +33,7 @@ function handleOriginalHtml(
microAppEntry: string,
originalHtml: string,
) {
const appName = api.pkg.name;
const appName = api.config.qiankun?.slave?.appName || api.pkg.name;
assert(
appName,
'[@umijs/plugin-qiankun]: You should have name in package.json',
Expand Down Expand Up @@ -302,15 +303,28 @@ export { MicroAppLink } from './MicroAppLink';
key: 'onLocalProxyStart',
type: api.ApplyPluginsType.event,
});

// 新增一个 modifyLocalProxyOpts 事件,支持用户自定义本地 proxy 代理参数
const modifyLocalProxyOpts = ((await api.applyPlugins({
key: 'modifyLocalProxyOpts',
type: api.ApplyPluginsType.modify,
initialValue: {},
})) ?? {}) as Partial<Options>;

const localProxyOpts: Partial<Options> = {
target: masterEntry,
secure: false,
ignorePath: false,
followRedirects: false,
changeOrigin: true,
selfHandleResponse: true,
...modifyLocalProxyOpts,
};

return createProxyMiddleware(
(pathname) => pathname !== '/local-dev-server',
{
target: masterEntry,
secure: false,
ignorePath: false,
followRedirects: false,
changeOrigin: true,
selfHandleResponse: true,
...localProxyOpts,
onProxyReq(proxyReq) {
api.applyPlugins({
key: 'onLocalProxyReq',
Expand All @@ -327,15 +341,26 @@ export { MicroAppLink } from './MicroAppLink';
res: any,
) => {
if (proxyRes.statusCode === 302) {
const hostname = (req as Request).hostname;
const { ignorePath = false } = localProxyOpts;
// 应该使用原始请求的 goto 链接,而非 masterEntry
const { hostname, url, protocol } = req as Request;
const port = process.env.PORT || api.appData?.port;
const goto = `${hostname}:${port}`;
const redirectUrl =
proxyRes.headers.location!.replace(
encodeURIComponent(new URL(masterEntry).hostname),
encodeURIComponent(goto),
) || masterEntry;

// 如果代理时忽略了 path,则需要把原始请求的 path 拼接到 gotoBasePart 上
const gotoBasePart = `${protocol}://${hostname}:${port}${
ignorePath && url ? url : '/'
}`;
const fromBasePart = masterEntry;
const locationUrl = proxyRes.headers.location || '';
// 只替换 search 参数的部分
const [originAndPath, searchParams] = locationUrl.split('?');
// 替换时只用替换 url base part 部分
const searchHandled = searchParams
? `?${searchParams.replace(
encodeURIComponent(fromBasePart),
encodeURIComponent(gotoBasePart),
)}`
: '';
const redirectUrl = `${originAndPath}${searchHandled}`;
const redirectMessage = `[@umijs/plugin-qiankun]: redirect to ${redirectUrl}`;

api.logger.info(redirectMessage);
Expand Down