diff --git a/src/dev-server/dev-server-utils.ts b/src/dev-server/dev-server-utils.ts index ffd99444513..4e3ba3ade22 100644 --- a/src/dev-server/dev-server-utils.ts +++ b/src/dev-server/dev-server-utils.ts @@ -88,14 +88,23 @@ export function isSsrStaticDataPath(pathname: string) { return fileName === 'page.state.json'; } -export function getSsrStaticDataPath(pathname: string) { - const parts = pathname.split('/'); +export function getSsrStaticDataPath(req: d.HttpRequest) { + const parts = req.url.href.split('/'); let fileName = parts[parts.length - 1]; const fileNameParts = fileName.split('?'); parts.pop(); + + let ssrPath = new URL(parts.join('/')).href; + if (!ssrPath.endsWith('/') && req.headers) { + const h = new Headers(req.headers); + if (h.get('referer').endsWith('/')) { + ssrPath += '/'; + } + } + return { - ssrPath: parts.join('/'), + ssrPath, fileName: fileNameParts[0], hasQueryString: typeof fileNameParts[1] === 'string' && fileNameParts[1].length > 0, }; diff --git a/src/dev-server/ssr-request.ts b/src/dev-server/ssr-request.ts index 64e28f1b2d2..516ff2bf45a 100644 --- a/src/dev-server/ssr-request.ts +++ b/src/dev-server/ssr-request.ts @@ -70,7 +70,7 @@ export async function ssrStaticDataRequest( if (!diagnostics.some(diagnostic => diagnostic.level === 'error')) { try { - const { ssrPath, hasQueryString } = getSsrStaticDataPath(req.url.href); + const { ssrPath, hasQueryString } = getSsrStaticDataPath(req); const url = new URL(ssrPath, req.url); const opts = getSsrHydrateOptions(devServerConfig, serverCtx, url); diff --git a/src/dev-server/test/util.spec.ts b/src/dev-server/test/util.spec.ts index 9ad3f57a130..87c8f4bdb5e 100644 --- a/src/dev-server/test/util.spec.ts +++ b/src/dev-server/test/util.spec.ts @@ -164,15 +164,48 @@ describe('getDevServerClientUrl', () => { expect(isSsrStaticDataPath('http://stenciljs.com/page.state.json')).toBe(true); }); - it('getSsrStaticDataPath', () => { - let r = getSsrStaticDataPath('http://stenciljs.com/page.static.json'); + it('getSsrStaticDataPath, root', () => { + const req: d.HttpRequest = { + url: new URL('http://stenciljs.com/page.static.json'), + method: 'GET', + acceptHeader: '', + searchParams: null, + }; + let r = getSsrStaticDataPath(req); expect(r.fileName).toBe('page.static.json'); expect(r.hasQueryString).toBe(false); - expect(r.ssrPath).toBe('http://stenciljs.com'); + expect(r.ssrPath).toBe('http://stenciljs.com/'); + }); - r = getSsrStaticDataPath('http://stenciljs.com/blog/page.static.json?1234'); + it('getSsrStaticDataPath, no trailing slash refer', () => { + const req: d.HttpRequest = { + url: new URL('http://stenciljs.com/blog/page.static.json?v=1234'), + method: 'GET', + acceptHeader: '', + searchParams: null, + headers: { + Referer: 'http://stenciljs.com/page', + }, + }; + const r = getSsrStaticDataPath(req); expect(r.fileName).toBe('page.static.json'); expect(r.hasQueryString).toBe(true); expect(r.ssrPath).toBe('http://stenciljs.com/blog'); }); + + it('getSsrStaticDataPath, with trailing slash refer', () => { + const req: d.HttpRequest = { + url: new URL('http://stenciljs.com/blog/page.static.json?v=1234'), + method: 'GET', + acceptHeader: '', + searchParams: null, + headers: { + Referer: 'http://stenciljs.com/page/', + }, + }; + const r = getSsrStaticDataPath(req); + expect(r.fileName).toBe('page.static.json'); + expect(r.hasQueryString).toBe(true); + expect(r.ssrPath).toBe('http://stenciljs.com/blog/'); + }); });