Skip to content

Commit 42251e9

Browse files
committed
fix(rsc-mf): avoid host fallback refetching same expose URL
1 parent cc65c74 commit 42251e9

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

tests/integration/rsc-mf/host/server/modern.server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,12 @@ const fetchRemoteManifestFallbackAsset = async ({
131131
remoteOrigin,
132132
pathname,
133133
search,
134+
requestUrl,
134135
}: {
135136
remoteOrigin: string;
136137
pathname: string;
137138
search: string;
139+
requestUrl: string;
138140
}) => {
139141
if (!isManifestFallbackEligiblePath(pathname)) {
140142
return undefined;
@@ -175,6 +177,9 @@ const fetchRemoteManifestFallbackAsset = async ({
175177
if (!fallbackAssetUrl) {
176178
return undefined;
177179
}
180+
if (fallbackAssetUrl === requestUrl) {
181+
return undefined;
182+
}
178183
const fallbackAssetResponse = await fetch(fallbackAssetUrl).catch(
179184
(): undefined => undefined,
180185
);
@@ -225,6 +230,7 @@ const proxyRemoteFederationAsset: MiddlewareHandler = async (c, next) => {
225230
remoteOrigin,
226231
pathname,
227232
search: reqUrl.search,
233+
requestUrl: remoteUrl,
228234
});
229235

230236
if (!resolvedUpstream || !resolvedUpstream.ok) {

tests/integration/rsc-mf/tests/modernServerConfig.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,55 @@ describe('rsc-mf host modern.server middleware contracts', () => {
762762
expect(context.res).toBeUndefined();
763763
});
764764

765+
it('falls through when manifest fallback resolves to original request URL', async () => {
766+
const handler = getProxyMiddlewareHandler();
767+
const next = jest.fn(async (): Promise<void> => undefined);
768+
const fetchMock = installFetchMock(
769+
jest
770+
.fn()
771+
.mockResolvedValueOnce(new Response('not-found', { status: 404 }))
772+
.mockResolvedValueOnce(
773+
new Response(
774+
JSON.stringify({
775+
exposes: [
776+
{
777+
assets: {
778+
js: {
779+
sync: [
780+
'static/js/async/__federation_expose_RemoteClientCounter.js',
781+
],
782+
async: [],
783+
},
784+
css: {
785+
sync: [],
786+
async: [],
787+
},
788+
},
789+
},
790+
],
791+
}),
792+
{
793+
status: 200,
794+
headers: {
795+
'content-type': 'application/json',
796+
},
797+
},
798+
),
799+
),
800+
);
801+
const context: { req: { url: string }; res?: Response } = {
802+
req: {
803+
url: 'http://127.0.0.1:3007/static/js/async/__federation_expose_RemoteClientCounter.js',
804+
},
805+
};
806+
807+
await withRemotePort('3999', () => handler(context, next));
808+
809+
expect(fetchMock).toHaveBeenCalledTimes(2);
810+
expect(next).toHaveBeenCalledTimes(1);
811+
expect(context.res).toBeUndefined();
812+
});
813+
765814
it('matches fallback chunks when manifest hash suffix includes non-hex characters', async () => {
766815
const handler = getProxyMiddlewareHandler();
767816
const next = jest.fn(async (): Promise<void> => undefined);

0 commit comments

Comments
 (0)