@vercel/microfrontends 2.3.3 → 2.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/bin/cli.cjs +92 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @vercel/microfrontends
|
|
2
2
|
|
|
3
|
+
## 2.3.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5fbc4e3: Preserve absolute URLs in query parameters when the local proxy normalizes request URLs and rewrites redirect Location headers.
|
|
8
|
+
- 9a01e16: Route Vercel Toolbar well-known requests through the local proxy to the locally running application that served the page. This supports `@vercel/toolbar@0.2.6+`, which uses `/.well-known/vercel-toolbar/*` for local dev server access.
|
|
9
|
+
|
|
10
|
+
## 2.3.4
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 7af3542: Prevent local proxy crashes when upstream errors occur after response headers have already been sent.
|
|
15
|
+
|
|
3
16
|
## 2.3.3
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/bin/cli.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var import_commander = require("commander");
|
|
|
30
30
|
// package.json
|
|
31
31
|
var package_default = {
|
|
32
32
|
name: "@vercel/microfrontends",
|
|
33
|
-
version: "2.3.
|
|
33
|
+
version: "2.3.5",
|
|
34
34
|
private: false,
|
|
35
35
|
description: "Defines configuration and utilities for microfrontends development",
|
|
36
36
|
keywords: [
|
|
@@ -2370,6 +2370,20 @@ var localAuthHtml = ({
|
|
|
2370
2370
|
var MFE_LOCAL_PROXY_HEADER = "x-vercel-mfe-local-proxy-origin";
|
|
2371
2371
|
var MFE_FLAG_VALUE = "vercel-mfe-flag-value";
|
|
2372
2372
|
var MFE_FLAG_VALUE_HEADER = `x-${MFE_FLAG_VALUE}`;
|
|
2373
|
+
var VERCEL_TOOLBAR_PROXY_BASE_PATH = "/.well-known/vercel-toolbar";
|
|
2374
|
+
function normalizeRepeatedSlashesInPath(url) {
|
|
2375
|
+
const searchStart = url.indexOf("?");
|
|
2376
|
+
const path7 = searchStart === -1 ? url : url.slice(0, searchStart);
|
|
2377
|
+
const search = searchStart === -1 ? "" : url.slice(searchStart);
|
|
2378
|
+
return `${path7.replaceAll(/\/[\\/]+/g, "/")}${search}`;
|
|
2379
|
+
}
|
|
2380
|
+
function rewriteRedirectLocation(locationHeader, localhost) {
|
|
2381
|
+
const redirectUrl = new import_node_url.URL(locationHeader, localhost);
|
|
2382
|
+
const localUrl = new import_node_url.URL(localhost);
|
|
2383
|
+
redirectUrl.protocol = localUrl.protocol;
|
|
2384
|
+
redirectUrl.host = localUrl.host;
|
|
2385
|
+
return redirectUrl.toString();
|
|
2386
|
+
}
|
|
2373
2387
|
var ProxyRequestRouter = class {
|
|
2374
2388
|
constructor(config, {
|
|
2375
2389
|
localApps
|
|
@@ -2494,6 +2508,15 @@ var ProxyRequestRouter = class {
|
|
|
2494
2508
|
middlewareMfeZone = void 0,
|
|
2495
2509
|
mfeFlagValue = void 0
|
|
2496
2510
|
}) {
|
|
2511
|
+
const toolbarTarget = this.checkVercelToolbar({
|
|
2512
|
+
path: path7,
|
|
2513
|
+
url,
|
|
2514
|
+
referer,
|
|
2515
|
+
applications
|
|
2516
|
+
});
|
|
2517
|
+
if (toolbarTarget) {
|
|
2518
|
+
return toolbarTarget;
|
|
2519
|
+
}
|
|
2497
2520
|
for (const application of Object.values(applications)) {
|
|
2498
2521
|
const target = this.getApplicationTarget(application);
|
|
2499
2522
|
if (middlewareMfeZone) {
|
|
@@ -2606,6 +2629,46 @@ var ProxyRequestRouter = class {
|
|
|
2606
2629
|
path: `${url.pathname}${url.search}`
|
|
2607
2630
|
};
|
|
2608
2631
|
}
|
|
2632
|
+
checkVercelToolbar({
|
|
2633
|
+
path: path7,
|
|
2634
|
+
url,
|
|
2635
|
+
referer = void 0,
|
|
2636
|
+
applications
|
|
2637
|
+
}) {
|
|
2638
|
+
const isVercelToolbarRequest = url.pathname === VERCEL_TOOLBAR_PROXY_BASE_PATH || url.pathname.startsWith(`${VERCEL_TOOLBAR_PROXY_BASE_PATH}/`);
|
|
2639
|
+
if (!isVercelToolbarRequest) {
|
|
2640
|
+
return null;
|
|
2641
|
+
}
|
|
2642
|
+
if (referer) {
|
|
2643
|
+
const refererURL = new import_node_url.URL(referer);
|
|
2644
|
+
const refererTarget = this.findMatchingApplication({
|
|
2645
|
+
path: `${refererURL.pathname}${refererURL.search}`,
|
|
2646
|
+
url: refererURL,
|
|
2647
|
+
applications
|
|
2648
|
+
}) ?? this.getDefaultHost(this.config);
|
|
2649
|
+
if (refererTarget.isLocal) {
|
|
2650
|
+
logger.debug(
|
|
2651
|
+
` ${path7} - Routing Vercel Toolbar request to referring application: ${formatProxyTarget(refererTarget)}`
|
|
2652
|
+
);
|
|
2653
|
+
return {
|
|
2654
|
+
...refererTarget,
|
|
2655
|
+
path: `${url.pathname}${url.search}`
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
const localApp = this.getSingleLocalApp();
|
|
2660
|
+
if (!localApp) {
|
|
2661
|
+
return null;
|
|
2662
|
+
}
|
|
2663
|
+
const target = this.getApplicationTarget(localApp);
|
|
2664
|
+
logger.debug(
|
|
2665
|
+
` ${path7} - Routing Vercel Toolbar request to only locally running application: ${formatProxyTarget(target)}`
|
|
2666
|
+
);
|
|
2667
|
+
return {
|
|
2668
|
+
...target,
|
|
2669
|
+
path: `${url.pathname}${url.search}`
|
|
2670
|
+
};
|
|
2671
|
+
}
|
|
2609
2672
|
checkNextSourceMap({ url }) {
|
|
2610
2673
|
const isSourceMap = (0, import_path_to_regexp3.pathToRegexp)("/__nextjs_source-map").test(url.pathname);
|
|
2611
2674
|
if (!isSourceMap) {
|
|
@@ -2662,20 +2725,26 @@ var ProxyRequestRouter = class {
|
|
|
2662
2725
|
}
|
|
2663
2726
|
isDefaultAppLocal() {
|
|
2664
2727
|
const defaultApp = this.config.getDefaultApplication();
|
|
2665
|
-
return
|
|
2666
|
-
this.localApps.find(
|
|
2667
|
-
(name) => name === defaultApp.name || name === defaultApp.packageName
|
|
2668
|
-
)
|
|
2669
|
-
);
|
|
2728
|
+
return this.isApplicationLocal(defaultApp);
|
|
2670
2729
|
}
|
|
2671
2730
|
getArbitraryLocalApp() {
|
|
2672
2731
|
for (const application of this.config.getAllApplications()) {
|
|
2673
|
-
|
|
2674
|
-
if (this.localApps.includes(name)) {
|
|
2732
|
+
if (this.isApplicationLocal(application)) {
|
|
2675
2733
|
return application;
|
|
2676
2734
|
}
|
|
2677
2735
|
}
|
|
2678
2736
|
}
|
|
2737
|
+
getSingleLocalApp() {
|
|
2738
|
+
const localApplications = this.config.getAllApplications().filter((application) => this.isApplicationLocal(application));
|
|
2739
|
+
return localApplications.length === 1 ? localApplications[0] : void 0;
|
|
2740
|
+
}
|
|
2741
|
+
isApplicationLocal(application) {
|
|
2742
|
+
return Boolean(
|
|
2743
|
+
this.localApps.find(
|
|
2744
|
+
(name) => name === application.name || name === application.packageName
|
|
2745
|
+
)
|
|
2746
|
+
);
|
|
2747
|
+
}
|
|
2679
2748
|
};
|
|
2680
2749
|
var LocalProxy = class {
|
|
2681
2750
|
constructor(config, {
|
|
@@ -2689,6 +2758,12 @@ var LocalProxy = class {
|
|
|
2689
2758
|
this.proxy = import_http_proxy.default.createProxyServer({ secure: true });
|
|
2690
2759
|
this.proxy.on("error", (err, req, res) => {
|
|
2691
2760
|
if (res instanceof http.ServerResponse) {
|
|
2761
|
+
if (res.destroyed || res.writableEnded)
|
|
2762
|
+
return;
|
|
2763
|
+
if (res.headersSent) {
|
|
2764
|
+
res.destroy(err);
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2692
2767
|
res.writeHead(500, {
|
|
2693
2768
|
"Content-Type": "text/plain"
|
|
2694
2769
|
});
|
|
@@ -2772,7 +2847,7 @@ var LocalProxy = class {
|
|
|
2772
2847
|
if (req.url?.includes("//")) {
|
|
2773
2848
|
const originalUrl = req.url;
|
|
2774
2849
|
if (originalUrl) {
|
|
2775
|
-
const normalizedUrl = originalUrl
|
|
2850
|
+
const normalizedUrl = normalizeRepeatedSlashesInPath(originalUrl);
|
|
2776
2851
|
if (normalizedUrl !== originalUrl) {
|
|
2777
2852
|
res.writeHead(307, {
|
|
2778
2853
|
Location: normalizedUrl,
|
|
@@ -2845,11 +2920,10 @@ var LocalProxy = class {
|
|
|
2845
2920
|
if (realRes.statusCode === 307 || realRes.statusCode === 308 || realRes.statusCode === 302 || realRes.statusCode === 301) {
|
|
2846
2921
|
const locationHeader = realRes.headers.location;
|
|
2847
2922
|
if (locationHeader) {
|
|
2848
|
-
|
|
2849
|
-
locationHeader
|
|
2923
|
+
realRes.headers.location = rewriteRedirectLocation(
|
|
2924
|
+
locationHeader,
|
|
2850
2925
|
localhost
|
|
2851
2926
|
);
|
|
2852
|
-
realRes.headers.location = redirectUrl.toString();
|
|
2853
2927
|
}
|
|
2854
2928
|
}
|
|
2855
2929
|
res.writeHead(realRes.statusCode || 200, realRes.headers);
|
|
@@ -2858,6 +2932,12 @@ var LocalProxy = class {
|
|
|
2858
2932
|
req.pipe(proxyReq);
|
|
2859
2933
|
proxyReq.on("error", (err) => {
|
|
2860
2934
|
logger.error("Proxy request error: ", err);
|
|
2935
|
+
if (res.destroyed || res.writableEnded)
|
|
2936
|
+
return;
|
|
2937
|
+
if (res.headersSent) {
|
|
2938
|
+
res.destroy(err);
|
|
2939
|
+
return;
|
|
2940
|
+
}
|
|
2861
2941
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
2862
2942
|
res.end(
|
|
2863
2943
|
`Error proxying request for ${target.application} to ${hostname}:${port}${path7}`
|