diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 32ff21246ad04..34ea5e9c9ff5e 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -198,21 +198,20 @@ export class ImageOptimizerCache { } } - const parsedUrl = parseUrl(url) - if (parsedUrl) { - const decodedPathname = decodeURIComponent(parsedUrl.pathname) - if (/\/_next\/image($|\/)/.test(decodedPathname)) { - return { - errorMessage: '"url" parameter cannot be recursive', - } - } - } - let isAbsolute: boolean if (url.startsWith('/')) { href = url isAbsolute = false + if ( + /\/_next\/image($|\/)/.test( + decodeURIComponent(parseUrl(url)?.pathname ?? '') + ) + ) { + return { + errorMessage: '"url" parameter cannot be recursive', + } + } } else { let hrefParsed: URL diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts index aecd8df96066e..92302d84c63ee 100644 --- a/test/integration/image-optimizer/test/util.ts +++ b/test/integration/image-optimizer/test/util.ts @@ -8,7 +8,6 @@ import { fetchViaHTTP, File, findPort, - getFetchUrl, killApp, launchApp, nextBuild, @@ -899,22 +898,28 @@ export function runTests(ctx) { expect(await res.text()).toBe(`"url" parameter is invalid`) }) - it('should fail with absolute next image url', async () => { - const fullUrl = getFetchUrl( - ctx.appPort, - '/_next/image?url=test.pngw=1&q=1' - ) - const query = { url: fullUrl, w: ctx.w, q: 1 } - const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) - expect(res.status).toBe(400) - expect(await res.text()).toBe(`"url" parameter cannot be recursive`) - }) + if (domains.length > 0) { + it('should pass with absolute next image url', async () => { + const fullUrl = + 'https://image-optimization-test.vercel.app/_next/image?url=%2Ffrog.jpg&w=1024&q=75' + const query = { url: fullUrl, w: ctx.w, q: 1 } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) + expect(res.status).toBe(200) + await expectWidth(res, ctx.w) + }) + } else { + it('should fail with absolute next image url', async () => { + const fullUrl = + 'https://image-optimization-test.vercel.app/_next/image?url=%2Ffrog.jpg&w=1024&q=75' + const query = { url: fullUrl, w: ctx.w, q: 1 } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) + expect(res.status).toBe(400) + expect(await res.text()).toBe(`"url" parameter is not allowed`) + }) + } it('should fail with relative image url with assetPrefix', async () => { - const fullUrl = getFetchUrl( - ctx.appPort, - `/assets/_next/image?url=test.pngw=1&q=1` - ) + const fullUrl = '/assets/_next/image?url=%2Ftest.png&w=128&q=75' const query = { url: fullUrl, w: ctx.w, q: 1 } const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) expect(res.status).toBe(400)