From e49d25b00bf3aa137932ed4e85a853690e73fed2 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 17 Jun 2025 18:35:10 -0400 Subject: [PATCH 01/10] fix(next/image): improve detect-content-type --- packages/next/src/server/image-optimizer.ts | 36 ++++++++++++++++-- .../detect-content-type.test.ts | 38 ++++++++++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 0b69e5b3fdd8b..15d7604db23c7 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -42,6 +42,7 @@ const ICO = 'image/x-icon' const ICNS = 'image/x-icns' const TIFF = 'image/tiff' const BMP = 'image/bmp' +const PDF = 'application/pdf' const CACHE_VERSION = 4 const ANIMATABLE_TYPES = [WEBP, PNG, GIF] const BYPASS_TYPES = [SVG, ICO, ICNS, BMP] @@ -152,7 +153,7 @@ async function writeToCacheDir( * it matches the "magic number" of known file signatures. * https://en.wikipedia.org/wiki/List_of_file_signatures */ -export function detectContentType(buffer: Buffer) { +export async function detectContentType(buffer: Buffer) { if ([0xff, 0xd8, 0xff].every((b, i) => buffer[i] === b)) { return JPEG } @@ -198,7 +199,36 @@ export function detectContentType(buffer: Buffer) { if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) { return BMP } - return null + + const sharp = getSharp(null) + const meta = await sharp(buffer) + .metadata() + .catch((_) => null) + + if (meta?.format) { + switch (meta.format) { + case 'avif': + return AVIF + case 'webp': + return WEBP + case 'png': + return PNG + case 'jpeg': + case 'jpg': + return JPEG + case 'gif': + return GIF + case 'svg': + return SVG + case 'tiff': + case 'tif': + return TIFF + case 'pdf': + return PDF + default: + return null + } + } } export class ImageOptimizerCache { @@ -703,7 +733,7 @@ export async function imageOptimizer( ) const upstreamType = - detectContentType(upstreamBuffer) || + (await detectContentType(upstreamBuffer)) || imageUpstream.contentType?.toLowerCase().trim() if (upstreamType) { diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index 06acff24bdc78..e57c8252a2dd7 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -8,42 +8,60 @@ const getImage = (filepath) => readFile(join(__dirname, filepath)) describe('detectContentType', () => { it('should return jpg', async () => { const buffer = await getImage('./images/test.jpg') - expect(detectContentType(buffer)).toBe('image/jpeg') + expect(await detectContentType(buffer)).toBe('image/jpeg') }) it('should return png', async () => { const buffer = await getImage('./images/test.png') - expect(detectContentType(buffer)).toBe('image/png') + expect(await detectContentType(buffer)).toBe('image/png') }) it('should return webp', async () => { const buffer = await getImage('./images/animated.webp') - expect(detectContentType(buffer)).toBe('image/webp') + expect(await detectContentType(buffer)).toBe('image/webp') }) it('should return svg', async () => { const buffer = await getImage('./images/test.svg') - expect(detectContentType(buffer)).toBe('image/svg+xml') + expect(await detectContentType(buffer)).toBe('image/svg+xml') }) it('should return svg for inline svg', async () => { const buffer = await getImage('./images/test-inline.svg') - expect(detectContentType(buffer)).toBe('image/svg+xml') + expect(await detectContentType(buffer)).toBe('image/svg+xml') + }) + it('should return svg when starts with space', async () => { + const buffer = Buffer.from( + ' ' + ) + expect(await detectContentType(buffer)).toBe('image/svg+xml') + }) + it('should return svg when starts with newline', async () => { + const buffer = Buffer.from( + '\n' + ) + expect(await detectContentType(buffer)).toBe('image/svg+xml') + }) + it('should return svg when starts with tab', async () => { + const buffer = Buffer.from( + '\t' + ) + expect(await detectContentType(buffer)).toBe('image/svg+xml') }) it('should return avif', async () => { const buffer = await getImage('./images/test.avif') - expect(detectContentType(buffer)).toBe('image/avif') + expect(await detectContentType(buffer)).toBe('image/avif') }) it('should return icon', async () => { const buffer = await getImage('./images/test.ico') - expect(detectContentType(buffer)).toBe('image/x-icon') + expect(await detectContentType(buffer)).toBe('image/x-icon') }) it('should return icns', async () => { const buffer = await getImage('./images/test.icns') - expect(detectContentType(buffer)).toBe('image/x-icns') + expect(await detectContentType(buffer)).toBe('image/x-icns') }) it('should return tiff', async () => { const buffer = await getImage('./images/test.tiff') - expect(detectContentType(buffer)).toBe('image/tiff') + expect(await detectContentType(buffer)).toBe('image/tiff') }) it('should return bmp', async () => { const buffer = await getImage('./images/test.bmp') - expect(detectContentType(buffer)).toBe('image/bmp') + expect(await detectContentType(buffer)).toBe('image/bmp') }) }) From e92127efef663cdde1b34371e81d4d766f228c9b Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 10:01:52 -0400 Subject: [PATCH 02/10] simplify upstream type detection --- packages/next/src/server/image-optimizer.ts | 97 +++++++++---------- test/integration/image-optimizer/test/util.ts | 27 +----- 2 files changed, 51 insertions(+), 73 deletions(-) diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 15d7604db23c7..6a121166297c9 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -732,58 +732,58 @@ export async function imageOptimizer( getMaxAge(imageUpstream.cacheControl) ) - const upstreamType = - (await detectContentType(upstreamBuffer)) || - imageUpstream.contentType?.toLowerCase().trim() - - if (upstreamType) { - if ( - upstreamType.startsWith('image/svg') && - !nextConfig.images.dangerouslyAllowSVG - ) { - if (!opts.silent) { - Log.error( - `The requested resource "${href}" has type "${upstreamType}" but dangerouslyAllowSVG is disabled` - ) - } - throw new ImageError( - 400, - '"url" parameter is valid but image type is not allowed' + const upstreamType = await detectContentType(upstreamBuffer) + + if ( + !upstreamType || + !upstreamType.startsWith('image/') || + upstreamType.includes(',') + ) { + if (!opts.silent) { + Log.error( + "The requested resource isn't a valid image for", + href, + 'received', + upstreamType ) } - if (ANIMATABLE_TYPES.includes(upstreamType) && isAnimated(upstreamBuffer)) { - if (!opts.silent) { - Log.warnOnce( - `The requested resource "${href}" is an animated image so it will not be optimized. Consider adding the "unoptimized" property to the .` - ) - } - return { - buffer: upstreamBuffer, - contentType: upstreamType, - maxAge, - etag: upstreamEtag, - upstreamEtag, - } + throw new ImageError(400, "The requested resource isn't a valid image.") + } + if ( + upstreamType.startsWith('image/svg') && + !nextConfig.images.dangerouslyAllowSVG + ) { + if (!opts.silent) { + Log.error( + `The requested resource "${href}" has type "${upstreamType}" but dangerouslyAllowSVG is disabled. Consider adding the "unoptimized" property to the .` + ) } - if (BYPASS_TYPES.includes(upstreamType)) { - return { - buffer: upstreamBuffer, - contentType: upstreamType, - maxAge, - etag: upstreamEtag, - upstreamEtag, - } + throw new ImageError( + 400, + '"url" parameter is valid but image type is not allowed' + ) + } + if (ANIMATABLE_TYPES.includes(upstreamType) && isAnimated(upstreamBuffer)) { + if (!opts.silent) { + Log.warnOnce( + `The requested resource "${href}" is an animated image so it will not be optimized. Consider adding the "unoptimized" property to the .` + ) } - if (!upstreamType.startsWith('image/') || upstreamType.includes(',')) { - if (!opts.silent) { - Log.error( - "The requested resource isn't a valid image for", - href, - 'received', - upstreamType - ) - } - throw new ImageError(400, "The requested resource isn't a valid image.") + return { + buffer: upstreamBuffer, + contentType: upstreamType, + maxAge, + etag: upstreamEtag, + upstreamEtag, + } + } + if (BYPASS_TYPES.includes(upstreamType)) { + return { + buffer: upstreamBuffer, + contentType: upstreamType, + maxAge, + etag: upstreamEtag, + upstreamEtag, } } @@ -792,7 +792,6 @@ export async function imageOptimizer( if (mimeType) { contentType = mimeType } else if ( - upstreamType?.startsWith('image/') && getExtension(upstreamType) && upstreamType !== WEBP && upstreamType !== AVIF diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts index 559222a5398ef..fd60cd81f24a6 100644 --- a/test/integration/image-optimizer/test/util.ts +++ b/test/integration/image-optimizer/test/util.ts @@ -219,27 +219,6 @@ export function runTests(ctx: RunTestsCtx) { await expectWidth(res, 256) }) - it('should maintain pic/pct', async () => { - const query = { w: ctx.w, q: 90, url: '/test.pic' } - const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) - expect(res.status).toBe(200) - expect(res.headers.get('Content-Type')).toContain('image/x-pict') - expect(res.headers.get('Cache-Control')).toBe( - `public, max-age=${isDev ? 0 : minimumCacheTTL}, must-revalidate` - ) - expect(res.headers.get('Vary')).toBe('Accept') - expect(res.headers.get('etag')).toBeTruthy() - expect(res.headers.get('Content-Disposition')).toBe( - `${contentDispositionType}; filename="test.pic"` - ) - const actual = await res.text() - const expected = await fs.readFile( - join(ctx.appDir, 'public', 'test.pic'), - 'utf8' - ) - expect(actual).toMatch(expected) - }) - it('should maintain animated gif', async () => { const query = { w: ctx.w, q: 90, url: '/animated.gif' } const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) @@ -381,7 +360,7 @@ export function runTests(ctx: RunTestsCtx) { const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts) expect(res.status).toBe(400) expect(await res.text()).toContain( - '"url" parameter is valid but image type is not allowed' + "The requested resource isn't a valid image" ) }) @@ -1092,8 +1071,8 @@ export function runTests(ctx: RunTestsCtx) { const opts = { headers: { accept: 'image/webp' } } const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts) expect(res.status).toBe(400) - expect(await res.text()).toBe( - `Unable to optimize image and unable to fallback to upstream image` + expect(await res.text()).toContain( + "The requested resource isn't a valid image" ) }) From 07f85c85b9d4cba54200ffe0e71403473d385d39 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 11:39:05 -0400 Subject: [PATCH 03/10] add tests for jxl and heic --- packages/next/src/server/image-optimizer.ts | 21 +++++++++++- packages/next/src/server/serve-static.ts | 2 ++ .../image-optimizer/app/public/test.heic | Bin 0 -> 2564 bytes .../image-optimizer/app/public/test.jxl | Bin 0 -> 46893 bytes test/integration/image-optimizer/test/util.ts | 32 ++++++++++++++++++ .../detect-content-type.test.ts | 9 +++++ test/unit/image-optimizer/images/test.heic | Bin 0 -> 2564 bytes test/unit/image-optimizer/images/test.jxl | Bin 0 -> 46893 bytes 8 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/integration/image-optimizer/app/public/test.heic create mode 100644 test/integration/image-optimizer/app/public/test.jxl create mode 100644 test/unit/image-optimizer/images/test.heic create mode 100644 test/unit/image-optimizer/images/test.jxl diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 6a121166297c9..0bf33e2447940 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -36,6 +36,8 @@ const AVIF = 'image/avif' const WEBP = 'image/webp' const PNG = 'image/png' const JPEG = 'image/jpeg' +const JXL = 'image/jxl' +const HEIC = 'image/heic' const GIF = 'image/gif' const SVG = 'image/svg+xml' const ICO = 'image/x-icon' @@ -45,7 +47,7 @@ const BMP = 'image/bmp' const PDF = 'application/pdf' const CACHE_VERSION = 4 const ANIMATABLE_TYPES = [WEBP, PNG, GIF] -const BYPASS_TYPES = [SVG, ICO, ICNS, BMP] +const BYPASS_TYPES = [SVG, ICO, ICNS, BMP, JXL, HEIC] const BLUR_IMG_SIZE = 8 // should match `next-image-loader` const BLUR_QUALITY = 70 // should match `next-image-loader` @@ -199,6 +201,23 @@ export async function detectContentType(buffer: Buffer) { if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) { return BMP } + if ([0xff, 0x0a].every((b, i) => buffer[i] === b)) { + return JXL + } + if ( + [ + 0x00, 0x00, 0x00, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0x0a, 0x87, 0x0a, + ].every((b, i) => buffer[i] === b) + ) { + return JXL + } + if ( + [0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63].every( + (b, i) => !b || buffer[i] === b + ) + ) { + return HEIC + } const sharp = getSharp(null) const meta = await sharp(buffer) diff --git a/packages/next/src/server/serve-static.ts b/packages/next/src/server/serve-static.ts index 4c3570641776b..3202f59fe721d 100644 --- a/packages/next/src/server/serve-static.ts +++ b/packages/next/src/server/serve-static.ts @@ -6,6 +6,8 @@ import send from 'next/dist/compiled/send' send.mime.define({ 'image/avif': ['avif'], 'image/x-icns': ['icns'], + 'image/jxl': ['jxl'], + 'image/heic': ['heic'], }) export function serveStatic( diff --git a/test/integration/image-optimizer/app/public/test.heic b/test/integration/image-optimizer/app/public/test.heic new file mode 100644 index 0000000000000000000000000000000000000000..748bdee125fac9ad63533da413de54fae0f46767 GIT binary patch literal 2564 zcmbtVdpMNq7Jp~PHIp2dN~t}Vl;V_2N7++m29ZlbZI@Dej2ZJeGv+fhggoxIid;fB zWpWv(rrJ^m=|s|8!0LW}n z49a04OaO(4u&q3i?E)UcV0$92bfsOzjmHu(Fdm9ACxk0dLI6;NDf*7TYjOw@&V~b{ z5CIF*nBd?;j1+K5|H0ZQBH}@;WHunm2mtWVVgLs$3}8{5D5ez#zZ-Fwi*q!hn0N^? zw}Lh^M973B4vQl25LAFd?SY_7KAg6g$>$1C0Uw6pbGb~OP-PuFY`93^<3cC-2LzJT z2Z0JO0GfadRxy}Dl(v1l2e$5y<|sGkI2CPOa&Rw|dzl)>6Q2B4u}E}mZi)A=6SbLVX2QvfVT0ifpQoGrKlfLfU2 z#m`WNfT3820N;2vyc-`Y0hk{EfF8{Cyj}k=>YmXS zi?sw?;zO6wC-T`91~;bk%)BB_o);hDqZZ=Lq1uyoDCeFN$LtgF)y7r#_<3se=HmdQ zBxb8&cuf-KdGbNkrg53>veRi z{buG-V+M^>{_b{K(rai}%I)>3nE2%4eU3L+!#5FX$>yt$mMqSkq`IknCIS2_f?2*- z@v(asgU&v+u8phs^cUkvY0J^bHlMW`RdpFbk14+;xiNC;m(Wgm?W)^ySY*;t(kAQQ zlVBP!<$ry&y({}TYc#u{EXV1fN)O>;Dj=!ReCf|s_ZQHbEu|cL-{jdT8~He| z_IXP0+u$SgH)BrX>Usmi{px*b?0<0Ndw1r2D;_sLyZNG|qM#4OH`SM2${NY+J{NWF zf$cu?lZ29AdSAa=dZUw6VN@@>5=e#ZG_GP^s?n$y#FD8M-D+)Wq|)17uo@i~=0-Sd zVY>&Ie@y23Ms7HP=2UuKUhNmiZL5C-u;Qj(%LdZ}32StU&(9X|I;r9{b=Is(t;o1NW_Q&1DZ& zH-zc6Ix@FTf7;Bwe4`fV**1LL>OCd!b$ET*B|P>(O3){VTy_pcb=05IzHB_>&h3cK zukW@-cQG#Hj~t{$KjFp&=(jveKK`~@H*k34bj0cRpR1g$cTH$p4pe$j7F1{P>F%A) zHUYD=wKKHlOz|@fjYTZ7omFt4ev9x5Z>djSx9>W^PW8%k(hFCw!(qpgCu{>8n=Y?r zoXpA^xDwQ_Ls%Z=ucdON@##_5BI1@B&BXx!W=+!Ml1*mAX{SQPS4Hk#Uz(>kwun9K zuch@23%938zf8qP_G%NWFCIBSOM29ozQ#L)Y$Vy=*m}$Q%}|r1t^Y>tHLoJ8+1Go2 z>X6JOlO(?VBF(-ftn!ilyYYlLwE{C)-M6B( zZF*mZ0)G~HuP{rqF7`eeo$<)DLv|sW`{dY%P8=tpXPHp5a$WPc(61-HHY8*P4_OPB zFX4|yB%h%A?Q}mro1wedLOj-0tQRlUvV8RpaXzf2x!bAA^=l8^?_OM{gRXe37!ds= zX}E%#R0j!S=oE2!II1qKK@xSp(y)7U=vZ$SV6 literal 0 HcmV?d00001 diff --git a/test/integration/image-optimizer/app/public/test.jxl b/test/integration/image-optimizer/app/public/test.jxl new file mode 100644 index 0000000000000000000000000000000000000000..d1a5a7d0da0294e2000808722841216f81165013 GIT binary patch literal 46893 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%0A*U0`)E z$w+ZBDZsGIu1k%U&Yb}HPc1W_(+}NP#N{k>bzY+=$vq7XB z=qv>-d!Qh{J~!Swrhg<}c!udvCC5No(eWvhS`kwX6-gJm@q9QOf8J>(4`` zJRKML*Lp2*YnCOUjP$?(+a}lzvYCy8m0vy*LXtDeLn6-DAwMJewlU;~k?6u{|KU}> zOa&C=i^_FEvAc}fTX-OsLRqIoI*?t z7ljKce3eKXU|A3sRgC*Jh#1(}pdALxK0rXvc*7Fhj`?P>Mz`ss1p(55mZl-$UJ#xk zpYp{T=8s;?~kka*eF%cC4cm11fxMzkWupA0fTWpE+3CK;5`#3 zVi>vo5aW-Sl?SR!^+5!^S7_X(yVU?6P+tKCZ;CTBh}Cbt4jf5Nyg8FK0))WcKC~fC zjw@n~#{g@YLzb6?FD=mb)F7Tdby2g;xfe4wwhoIBg%~AFD~ELi$Q`0#>}g+ye}YSP z4TF*9Am|Jhff>9Ge0;m4j)VL42@IdCh@tloAw1&pHtg$k2kvT2k=%5z3n(5Ma-{^g z5f6tQW4#Xv;tlLbpPvqj7(}?Nh_5{;PR!8&-&CL}w<_K0hEFIBd0BhWZMcR_^i24u zvJZp5LvrJ#D?jxR;G!gZmW3ruC+#kjSAD?tC-m;D>n&uBRBHLh?J_gR$*<83;rFIOp1WEp1zBBrS`xsbfU>^Zfd$aTCUD=THL({25mB^o)Z zrpR}SW17{MGKs4wK>bzH+i9`QwxWzqSUs;7EM2EcG-7{h_-q_Y9VbhLKBEIcOmqg0 z!#?Vz_7>Q0)ft}GGn%kPU|y|bit(>{e1ggV!hFo za@S+;CSny;18AesBLb(<^MTIi3pxmdLlGcGqLjKvY11kyM%#ks7k+yV~-(u*mjKOC!obF_*35CP_Bx-96tZ zl0bR~&N$~bMla)jR(?(7RJ7{PTxC!{7K}=dWCiAg8Dya!mT%0madgbCnAp$&^19xS zpKd5IURFwf>NJ8P)py_d6F!+pF$16;?eQXJ1`YNz)HLkGG=fths`dy2?DYrDNT}q| z)7Fw&pY^Gby{PXLBayrTEG`SSdPQPraJSwMPp^d^hMO!79AGhPNicW%w7+2I=|4BL z%O$GFWBSP6H*Xdm(cQ=)D3R_w!GIIBeemhrqJ)~t7fTNR-oJ?co?63M1?U$z=e67b ztQJh*NzE5K?lx6OdS@-0bV@9%czS)=9Nmk(msHEVfWrZ<{SG=DcZE~+vcP~QXE$EG z!9voJ_}kpFWdjcqUd z{nk$P@ukaSONgoJw5o>7Re{}chJ3kWd|1x|6aX^Ad*`Tf>-Jg;*=GocvbO7^`d6&n=Om@T&)dx3{Losr>< zDj5X{#S9jPq;_Ng%yPY@8N$%(%Kd5eP+9Zg3I}C0bf-p~ZtXgAfF2}xexyvX;_&2c zVG~I}Hj<&AYp@H$IP^s4<1sLdf>uDt>xW2VQVl+kR*Q>oeD{QfRAnBq7cu>=jvnPoo^R9voXRdh(6slD zusKVAjaBB!R0VUB>`~z8qcLz0FfYJ0XNpwdU>A$yXrla}CB5tQS_Ua|E9a}}!AMaP zb@3vuKtt$};C3nZRT3ZHqa4u#F8A(@yn)~WLMCSb@dDMCL$v0Hr-=H0^K0TI%n<%l zyp)EdYk-S1Pa2f^fy%sO=l&oDz(SIZY$l|y6?WfitFj*VvtZXP$IDpUr4t!fnQprG z@7icIsBg`ile#WeAJ)H!K<%rOli2N=Q>YE8%na zUWI?mmcgr{70e>d)kVA@E9&O|0rWju8;`vuH;a;gnxdUW5}Nl6LMCY*lKA~BoG(|P z1qtL6dg{n+@X#gxObdwwf@NI7rigWUbPKaO}wn| zR^vp;FP1S8YdoFkR?-Q@L4=J*Bse4(NZPgJl54uaS0#d;g$bqOy|5>R46V+&H`Zg2 zam%lWYa1KqqkE8=)4!S+E1ZQCeH)pakV*x#WkwF=NOrK`Bx}X{9=B~|DC?)eYqI8B z+6ng+2Ry%1f{L`)|Az*aNT_)6+kd$ekaI^FRDu2k$Dgzi`yI+oujS z$SoH-P@#+jM@PXJ7|8fzR|dvxX8GT;2X?#2hJWWHVhO*Q${5Z~O@(ShusnaNBVtqQ ztH`{_hZ65^{&y#3TU~Qcq7?w9IKY4)8Y}kiOtUzBUIk4iYT-cZn5NTl4`QPLfVj!0 zy@{TAK}9m6lmnpC?q^hqlW52iqeYp-%~SiC>}(&#ZeS+YFo=|D0thRVZL!p&e!yxN zA&8yQXjrKojZIRLv1Gex07!}56kWu`lHMzAZ_c-cBYlw;J8lb4Z_M2O?BsO?A@zRH zy>0|6q?idjg50#ei z??nC_N_^zm*sJSo#Epm~n4hJ^jOyTa!KQoz^vrP2k9?2D11Z(s);(08+|gTwmV_ZH zW;NKj{Yn?66VKn)P|r>8(J5&w7Vmvc5>98$4sOFIU+4ov{uz#9`jhz#|Ln%Poe6o@ za{xnO761U(Z$Azq85RJ%{{q?oWVXlSUM)a^cqO5m2~Z;cZu_`6GG3+s z#T{3cjh|2WFG}Zgva`#%((PilFc;{rOHW$428`d$CEsHFi?cy-k_=N(=lOlE1DSP5 zL(ez*gX!^eh&=${D8s}*sTJSY&IE5PNdU%bn)VW5-uxt_@&we3p4iar!6l%^EON)| zT{oI5eJ@rVF>T_uRyIqW<@`NGYC7ArdJiVTG6RH=Ie}$I6^Z7vz$pv?7hvX$=cUs{ z`MO)S0Jnm}ddjciBD~|Njc`lLzNjb-dI3K2ugPZ!{?tp#n!*PY+ia~&n0uxex#rGA zgA(?f>mp(J#2pvYHVw0`Y&(K^p$LGi_{irOPnQG3p$jfEqeXa2a|zLY_4g?PvXtau zMQ-2k@{6@jctWiSnDfpU*>zYtqaf`jrl1CD`~r$;+`wiLM+@vreW>G)X`G8Mx_^;w0OuKMf15dVRAP}}K_HNyl7^?ZIMoikwEIIU zZB|n&${-rUV);Rc7*unuXkQvDQfTQogQ_6aa_^czE>A4;#+-mm-O1h&Pax|Be9nUn zX$noMAqPv_Q*9&+mk)Z6p|H|)qx0Y)YWVN|6TofTCuxNwvTU1!ky)}fWRI6y_iU9U zEu6)gka-6H9pyCuEVS$|qi#L(bIX$H?`J6@p;uK9-9gFRUe<^O=qgW^m9;oUra)cL z*?ba@fI_1%9?ZITxF>g&X5$g#D`kY5b|xVaJOLCU7$4f>I0}@hoO(Uez1yCyAtRQ{ zvVH9aDGk6w-mC3pmeWPRyXj=-{S4MC5GbVL`i9n`ifZ#sT*1$U6`Qsj)iBh>uzlG=`%w(etGRHDuy_5gsR3={vPR(xYS6RF9M J0ds?+)B}`C-=qKl literal 0 HcmV?d00001 diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts index fd60cd81f24a6..c0f295d82dde4 100644 --- a/test/integration/image-optimizer/test/util.ts +++ b/test/integration/image-optimizer/test/util.ts @@ -219,6 +219,38 @@ export function runTests(ctx: RunTestsCtx) { await expectWidth(res, 256) }) + it('should maintain jxl', async () => { + const query = { w: ctx.w, q: 90, url: '/test.jxl' } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) + expect(res.status).toBe(200) + expect(res.headers.get('Content-Type')).toContain('image/jxl') + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=${isDev ? 0 : minimumCacheTTL}, must-revalidate` + ) + expect(res.headers.get('Vary')).toBe('Accept') + expect(res.headers.get('etag')).toBeTruthy() + expect(res.headers.get('Content-Disposition')).toBe( + `${contentDispositionType}; filename="test.jxl"` + ) + await expectWidth(res, 800) + }) + + it('should maintain heic', async () => { + const query = { w: ctx.w, q: 90, url: '/test.heic' } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) + expect(res.status).toBe(200) + expect(res.headers.get('Content-Type')).toContain('image/heic') + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=${isDev ? 0 : minimumCacheTTL}, must-revalidate` + ) + expect(res.headers.get('Vary')).toBe('Accept') + expect(res.headers.get('etag')).toBeTruthy() + expect(res.headers.get('Content-Disposition')).toBe( + `${contentDispositionType}; filename="test.heic"` + ) + await expectWidth(res, 400) + }) + it('should maintain animated gif', async () => { const query = { w: ctx.w, q: 90, url: '/animated.gif' } const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index e57c8252a2dd7..a936e960b66c2 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -56,6 +56,15 @@ describe('detectContentType', () => { const buffer = await getImage('./images/test.icns') expect(await detectContentType(buffer)).toBe('image/x-icns') }) + it('should return jxl', async () => { + const buffer = await getImage('./images/test.jxl') + expect(await detectContentType(buffer)).toBe('image/jxl') + }) + it('should return heic', async () => { + const buffer = await getImage('./images/test.heic') + console.log('buffer', buffer) + expect(await detectContentType(buffer)).toBe('image/heic') + }) it('should return tiff', async () => { const buffer = await getImage('./images/test.tiff') expect(await detectContentType(buffer)).toBe('image/tiff') diff --git a/test/unit/image-optimizer/images/test.heic b/test/unit/image-optimizer/images/test.heic new file mode 100644 index 0000000000000000000000000000000000000000..748bdee125fac9ad63533da413de54fae0f46767 GIT binary patch literal 2564 zcmbtVdpMNq7Jp~PHIp2dN~t}Vl;V_2N7++m29ZlbZI@Dej2ZJeGv+fhggoxIid;fB zWpWv(rrJ^m=|s|8!0LW}n z49a04OaO(4u&q3i?E)UcV0$92bfsOzjmHu(Fdm9ACxk0dLI6;NDf*7TYjOw@&V~b{ z5CIF*nBd?;j1+K5|H0ZQBH}@;WHunm2mtWVVgLs$3}8{5D5ez#zZ-Fwi*q!hn0N^? zw}Lh^M973B4vQl25LAFd?SY_7KAg6g$>$1C0Uw6pbGb~OP-PuFY`93^<3cC-2LzJT z2Z0JO0GfadRxy}Dl(v1l2e$5y<|sGkI2CPOa&Rw|dzl)>6Q2B4u}E}mZi)A=6SbLVX2QvfVT0ifpQoGrKlfLfU2 z#m`WNfT3820N;2vyc-`Y0hk{EfF8{Cyj}k=>YmXS zi?sw?;zO6wC-T`91~;bk%)BB_o);hDqZZ=Lq1uyoDCeFN$LtgF)y7r#_<3se=HmdQ zBxb8&cuf-KdGbNkrg53>veRi z{buG-V+M^>{_b{K(rai}%I)>3nE2%4eU3L+!#5FX$>yt$mMqSkq`IknCIS2_f?2*- z@v(asgU&v+u8phs^cUkvY0J^bHlMW`RdpFbk14+;xiNC;m(Wgm?W)^ySY*;t(kAQQ zlVBP!<$ry&y({}TYc#u{EXV1fN)O>;Dj=!ReCf|s_ZQHbEu|cL-{jdT8~He| z_IXP0+u$SgH)BrX>Usmi{px*b?0<0Ndw1r2D;_sLyZNG|qM#4OH`SM2${NY+J{NWF zf$cu?lZ29AdSAa=dZUw6VN@@>5=e#ZG_GP^s?n$y#FD8M-D+)Wq|)17uo@i~=0-Sd zVY>&Ie@y23Ms7HP=2UuKUhNmiZL5C-u;Qj(%LdZ}32StU&(9X|I;r9{b=Is(t;o1NW_Q&1DZ& zH-zc6Ix@FTf7;Bwe4`fV**1LL>OCd!b$ET*B|P>(O3){VTy_pcb=05IzHB_>&h3cK zukW@-cQG#Hj~t{$KjFp&=(jveKK`~@H*k34bj0cRpR1g$cTH$p4pe$j7F1{P>F%A) zHUYD=wKKHlOz|@fjYTZ7omFt4ev9x5Z>djSx9>W^PW8%k(hFCw!(qpgCu{>8n=Y?r zoXpA^xDwQ_Ls%Z=ucdON@##_5BI1@B&BXx!W=+!Ml1*mAX{SQPS4Hk#Uz(>kwun9K zuch@23%938zf8qP_G%NWFCIBSOM29ozQ#L)Y$Vy=*m}$Q%}|r1t^Y>tHLoJ8+1Go2 z>X6JOlO(?VBF(-ftn!ilyYYlLwE{C)-M6B( zZF*mZ0)G~HuP{rqF7`eeo$<)DLv|sW`{dY%P8=tpXPHp5a$WPc(61-HHY8*P4_OPB zFX4|yB%h%A?Q}mro1wedLOj-0tQRlUvV8RpaXzf2x!bAA^=l8^?_OM{gRXe37!ds= zX}E%#R0j!S=oE2!II1qKK@xSp(y)7U=vZ$SV6 literal 0 HcmV?d00001 diff --git a/test/unit/image-optimizer/images/test.jxl b/test/unit/image-optimizer/images/test.jxl new file mode 100644 index 0000000000000000000000000000000000000000..d1a5a7d0da0294e2000808722841216f81165013 GIT binary patch literal 46893 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%0A*U0`)E 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 J0ds?+)B}`C-=qKl literal 0 HcmV?d00001 From 76c7dcd371ce2ad57d55c3c724d9fbd237dc5efb Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 11:47:42 -0400 Subject: [PATCH 04/10] add test for pdf --- packages/next/src/server/image-optimizer.ts | 3 +++ .../image-optimizer/app/public/test.pdf | Bin 0 -> 6128 bytes test/integration/image-optimizer/test/util.ts | 10 ++++++++++ .../image-optimizer/detect-content-type.test.ts | 5 +++++ test/unit/image-optimizer/images/test.pdf | Bin 0 -> 6128 bytes 5 files changed, 18 insertions(+) create mode 100644 test/integration/image-optimizer/app/public/test.pdf create mode 100644 test/unit/image-optimizer/images/test.pdf diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 0bf33e2447940..b904865f253ce 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -218,6 +218,9 @@ export async function detectContentType(buffer: Buffer) { ) { return HEIC } + if ([0x25, 0x50, 0x44, 0x46, 0x2d].every((b, i) => buffer[i] === b)) { + return PDF + } const sharp = getSharp(null) const meta = await sharp(buffer) diff --git a/test/integration/image-optimizer/app/public/test.pdf b/test/integration/image-optimizer/app/public/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5dd8db5d9d738edf262a17ed118545b1ee35394f GIT binary patch literal 6128 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 { + const query = { w: ctx.w, q: 90, url: '/test.pdf' } + const opts = { headers: { accept: 'image/webp' } } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts) + expect(res.status).toBe(400) + expect(await res.text()).toContain( + "The requested resource isn't a valid image" + ) + }) + it('should maintain ico format', async () => { const query = { w: ctx.w, q: 90, url: `/test.ico` } const opts = { headers: { accept: 'image/webp' } } diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index a936e960b66c2..8ecda4979a256 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -65,6 +65,11 @@ describe('detectContentType', () => { console.log('buffer', buffer) expect(await detectContentType(buffer)).toBe('image/heic') }) + it('should return pdf', async () => { + const buffer = await getImage('./images/test.pdf') + console.log('buffer', buffer) + expect(await detectContentType(buffer)).toBe('application/pdf') + }) it('should return tiff', async () => { const buffer = await getImage('./images/test.tiff') expect(await detectContentType(buffer)).toBe('image/tiff') diff --git a/test/unit/image-optimizer/images/test.pdf b/test/unit/image-optimizer/images/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5dd8db5d9d738edf262a17ed118545b1ee35394f GIT binary patch literal 6128 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 Date: Mon, 28 Jul 2025 11:50:55 -0400 Subject: [PATCH 05/10] remove console.log() --- test/unit/image-optimizer/detect-content-type.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index 8ecda4979a256..9a86ab9f0463b 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -62,12 +62,10 @@ describe('detectContentType', () => { }) it('should return heic', async () => { const buffer = await getImage('./images/test.heic') - console.log('buffer', buffer) expect(await detectContentType(buffer)).toBe('image/heic') }) it('should return pdf', async () => { const buffer = await getImage('./images/test.pdf') - console.log('buffer', buffer) expect(await detectContentType(buffer)).toBe('application/pdf') }) it('should return tiff', async () => { From 3847e4a10771a2f4380e6c7eff34be171cbdceda Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 14:39:35 -0400 Subject: [PATCH 06/10] remove assertions on nextOutput since its redundant when we already check status code --- test/integration/image-optimizer/test/util.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts index 9b996ba79a054..0e1877825ac47 100644 --- a/test/integration/image-optimizer/test/util.ts +++ b/test/integration/image-optimizer/test/util.ts @@ -350,12 +350,6 @@ export function runTests(ctx: RunTestsCtx) { 'utf8' ) expect(actual).toMatch(expected) - expect(ctx.nextOutput).not.toContain( - `The requested resource isn't a valid image` - ) - expect(ctx.nextOutput).not.toContain( - `valid but image type is not allowed` - ) }) } else { it('should not allow vector svg', async () => { From 4ccf14183b2a39c45b8c665f61141507b3d34f10 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 14:51:47 -0400 Subject: [PATCH 07/10] add exhausive switch cases --- packages/next/src/server/image-optimizer.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index b904865f253ce..e317b6838592c 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -155,7 +155,9 @@ async function writeToCacheDir( * it matches the "magic number" of known file signatures. * https://en.wikipedia.org/wiki/List_of_file_signatures */ -export async function detectContentType(buffer: Buffer) { +export async function detectContentType( + buffer: Buffer +): Promise { if ([0xff, 0xd8, 0xff].every((b, i) => buffer[i] === b)) { return JPEG } @@ -242,15 +244,31 @@ export async function detectContentType(buffer: Buffer) { return GIF case 'svg': return SVG + case 'jxl': + return JXL case 'tiff': case 'tif': return TIFF case 'pdf': return PDF + case 'dcraw': + case 'dz': + case 'exr': + case 'fits': + case 'heif': + case 'input': + case 'jp2': + case 'magick': + case 'openslide': + case 'ppm': + case 'rad': + case 'raw': + case 'v': default: return null } } + return null } export class ImageOptimizerCache { From 23171202528e5516c9991a965c7065c981fdd5c2 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 15:30:35 -0400 Subject: [PATCH 08/10] add test for jp2 --- packages/next/src/server/image-optimizer.ts | 84 ++++++++++-------- .../image-optimizer/app/public/test.jp2 | Bin 0 -> 242 bytes test/integration/image-optimizer/test/util.ts | 16 ++++ .../detect-content-type.test.ts | 4 + test/unit/image-optimizer/images/test.jp2 | Bin 0 -> 242 bytes 5 files changed, 65 insertions(+), 39 deletions(-) create mode 100644 test/integration/image-optimizer/app/public/test.jp2 create mode 100644 test/unit/image-optimizer/images/test.jp2 diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index e317b6838592c..9f9e862caada9 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -37,6 +37,7 @@ const WEBP = 'image/webp' const PNG = 'image/png' const JPEG = 'image/jpeg' const JXL = 'image/jxl' +const JP2 = 'image/jp2' const HEIC = 'image/heic' const GIF = 'image/gif' const SVG = 'image/svg+xml' @@ -223,50 +224,55 @@ export async function detectContentType( if ([0x25, 0x50, 0x44, 0x46, 0x2d].every((b, i) => buffer[i] === b)) { return PDF } + if ( + [ + 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a, + ].every((b, i) => buffer[i] === b) + ) { + return JP2 + } const sharp = getSharp(null) const meta = await sharp(buffer) .metadata() .catch((_) => null) - - if (meta?.format) { - switch (meta.format) { - case 'avif': - return AVIF - case 'webp': - return WEBP - case 'png': - return PNG - case 'jpeg': - case 'jpg': - return JPEG - case 'gif': - return GIF - case 'svg': - return SVG - case 'jxl': - return JXL - case 'tiff': - case 'tif': - return TIFF - case 'pdf': - return PDF - case 'dcraw': - case 'dz': - case 'exr': - case 'fits': - case 'heif': - case 'input': - case 'jp2': - case 'magick': - case 'openslide': - case 'ppm': - case 'rad': - case 'raw': - case 'v': - default: - return null - } + switch (meta?.format) { + case 'avif': + return AVIF + case 'webp': + return WEBP + case 'png': + return PNG + case 'jpeg': + case 'jpg': + return JPEG + case 'gif': + return GIF + case 'svg': + return SVG + case 'jxl': + return JXL + case 'jp2': + return JP2 + case 'tiff': + case 'tif': + return TIFF + case 'pdf': + return PDF + case 'dcraw': + case 'dz': + case 'exr': + case 'fits': + case 'heif': + case 'input': + case 'magick': + case 'openslide': + case 'ppm': + case 'rad': + case 'raw': + case 'v': + default: + return null } return null } diff --git a/test/integration/image-optimizer/app/public/test.jp2 b/test/integration/image-optimizer/app/public/test.jp2 new file mode 100644 index 0000000000000000000000000000000000000000..0aa9268d723ff320c7352abfad1d312125b9921c GIT binary patch literal 242 zcmZQzVBpCLP*C9IYUg5LU=T?wsVvAUFj4@r8KAT-kj?;d#WFKeihwjD7_;!R18D{Z z{^b0eB9IURg8&dO1u9Pd@BcrL!3Zn{Q4D5c;j{2FGQ!dSAO;?w8lVmq76!)uF$^pY z4gXUZR2dkZi&7IyQd1O?Di!<-QuDk5T-_DQQj3Z+^Yavp^i1^({!d^4xt@VR3#f7O e@qavQOt<+#6oZTW`9B6cEaKuIirMk}|C<2Q&o8L} literal 0 HcmV?d00001 diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts index 0e1877825ac47..85707d353f853 100644 --- a/test/integration/image-optimizer/test/util.ts +++ b/test/integration/image-optimizer/test/util.ts @@ -251,6 +251,22 @@ export function runTests(ctx: RunTestsCtx) { await expectWidth(res, 400) }) + it('should maintain jp2', async () => { + const query = { w: ctx.w, q: 90, url: '/test.jp2' } + const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) + expect(res.status).toBe(200) + expect(res.headers.get('Content-Type')).toContain('image/jp2') + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=${isDev ? 0 : minimumCacheTTL}, must-revalidate` + ) + expect(res.headers.get('Vary')).toBe('Accept') + expect(res.headers.get('etag')).toBeTruthy() + expect(res.headers.get('Content-Disposition')).toBe( + `${contentDispositionType}; filename="test.jp2"` + ) + await expectWidth(res, 1) + }) + it('should maintain animated gif', async () => { const query = { w: ctx.w, q: 90, url: '/animated.gif' } const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {}) diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index 9a86ab9f0463b..87ad8029d4ae7 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -60,6 +60,10 @@ describe('detectContentType', () => { const buffer = await getImage('./images/test.jxl') expect(await detectContentType(buffer)).toBe('image/jxl') }) + it('should return jp2', async () => { + const buffer = await getImage('./images/test.jp2') + expect(await detectContentType(buffer)).toBe('image/jp2') + }) it('should return heic', async () => { const buffer = await getImage('./images/test.heic') expect(await detectContentType(buffer)).toBe('image/heic') diff --git a/test/unit/image-optimizer/images/test.jp2 b/test/unit/image-optimizer/images/test.jp2 new file mode 100644 index 0000000000000000000000000000000000000000..0aa9268d723ff320c7352abfad1d312125b9921c GIT binary patch literal 242 zcmZQzVBpCLP*C9IYUg5LU=T?wsVvAUFj4@r8KAT-kj?;d#WFKeihwjD7_;!R18D{Z z{^b0eB9IURg8&dO1u9Pd@BcrL!3Zn{Q4D5c;j{2FGQ!dSAO;?w8lVmq76!)uF$^pY z4gXUZR2dkZi&7IyQd1O?Di!<-QuDk5T-_DQQj3Z+^Yavp^i1^({!d^4xt@VR3#f7O e@qavQOt<+#6oZTW`9B6cEaKuIirMk}|C<2Q&o8L} literal 0 HcmV?d00001 From 68b18f239bd4c43004191b32c31b78042457bfbb Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 15:54:38 -0400 Subject: [PATCH 09/10] fix test to use valid svg --- .../production/fixture/public/xss.svg | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/production/pages-dir/production/fixture/public/xss.svg b/test/production/pages-dir/production/fixture/public/xss.svg index c3e80bb95a209..6788976bed318 100644 --- a/test/production/pages-dir/production/fixture/public/xss.svg +++ b/test/production/pages-dir/production/fixture/public/xss.svg @@ -1,9 +1,11 @@ - - - XSS - - -

safe

- - - + + + + + + From 75407314c183d617e031109147a06c529f69ffcc Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 28 Jul 2025 16:01:48 -0400 Subject: [PATCH 10/10] add missing exhaustive check --- packages/next/src/server/image-optimizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 9f9e862caada9..125849d9c0e81 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -271,10 +271,10 @@ export async function detectContentType( case 'rad': case 'raw': case 'v': + case undefined: default: return null } - return null } export class ImageOptimizerCache {