Skip to content

Commit daf36fa

Browse files
authored
detect more image types (#830)
Sync of vercel/next.js#82118
1 parent 67e71b9 commit daf36fa

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

.changeset/lucky-cups-live.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@opennextjs/cloudflare": patch
3+
---
4+
5+
detect more image types
6+
7+
Sync of <https://github.com/vercel/next.js/pull/82118>

packages/cloudflare/src/cli/templates/images.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,16 @@ export async function fetchImage(fetcher: Fetcher | undefined, imageUrl: string,
9393
}
9494

9595
if (!contentType) {
96-
// Fallback to the sanitized upstream header when the type can not be detected
96+
// Fallback to upstream header when the type can not be detected
9797
// https://github.com/vercel/next.js/blob/d76f0b1/packages/next/src/server/image-optimizer.ts#L748
98-
const header = imgResponse.headers.get("content-type") ?? "";
99-
if (header.startsWith("image/") && !header.includes(",")) {
100-
contentType = header;
101-
}
98+
contentType = imgResponse.headers.get("content-type") ?? "";
99+
}
100+
101+
// Sanitize the content type:
102+
// - Accept images only
103+
// - Reject multiple content types
104+
if (!contentType.startsWith("image/") || contentType.includes(",")) {
105+
contentType = undefined;
102106
}
103107

104108
if (contentType && !(contentType === SVG && !__IMAGES_ALLOW_SVG__)) {
@@ -167,12 +171,17 @@ const AVIF = "image/avif";
167171
const WEBP = "image/webp";
168172
const PNG = "image/png";
169173
const JPEG = "image/jpeg";
174+
const JXL = "image/jxl";
175+
const JP2 = "image/jp2";
176+
const HEIC = "image/heic";
170177
const GIF = "image/gif";
171178
const SVG = "image/svg+xml";
172179
const ICO = "image/x-icon";
173180
const ICNS = "image/x-icns";
174181
const TIFF = "image/tiff";
175182
const BMP = "image/bmp";
183+
// pdf will be rejected (not an `image/...` type)
184+
const PDF = "application/pdf";
176185

177186
/**
178187
* Detects the content type by looking at the first few bytes of a file
@@ -216,6 +225,25 @@ export function detectContentType(buffer: Uint8Array) {
216225
if ([0x42, 0x4d].every((b, i) => buffer[i] === b)) {
217226
return BMP;
218227
}
228+
if ([0xff, 0x0a].every((b, i) => buffer[i] === b)) {
229+
return JXL;
230+
}
231+
if (
232+
[0x00, 0x00, 0x00, 0x0c, 0x4a, 0x58, 0x4c, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every((b, i) => buffer[i] === b)
233+
) {
234+
return JXL;
235+
}
236+
if ([0, 0, 0, 0, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63].every((b, i) => !b || buffer[i] === b)) {
237+
return HEIC;
238+
}
239+
if ([0x25, 0x50, 0x44, 0x46, 0x2d].every((b, i) => buffer[i] === b)) {
240+
return PDF;
241+
}
242+
if (
243+
[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a].every((b, i) => buffer[i] === b)
244+
) {
245+
return JP2;
246+
}
219247
}
220248

221249
declare global {

0 commit comments

Comments
 (0)