Skip to content

Commit e657f54

Browse files
committed
fix: allow webp images to be processed and not just generated
1 parent ccbc84f commit e657f54

3 files changed

Lines changed: 175 additions & 1 deletion

File tree

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ exports.handler = async (event) => {
2626
return response;
2727
}
2828

29-
const allowedContentTypes = ['image/gif', 'image/jpeg', 'image/png'];
29+
const allowedContentTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/webp'];
3030
const key = decodeURIComponent(request.uri.substring(1));
3131
const objectResponse = await fetchOriginalImageFromS3(bucketInfo, key);
3232

tests/image-processing-integration.test.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ describe('Image Processing Integration', () => {
4949
})
5050
.gif()
5151
.toFile(path.join(fixturesDir, 'test-image.gif'));
52+
53+
await sharp({
54+
create: {
55+
width: 400,
56+
height: 300,
57+
channels: 3,
58+
background: { r: 0, g: 0, b: 255 },
59+
},
60+
})
61+
.webp()
62+
.toFile(path.join(fixturesDir, 'test-image.webp'));
5263
});
5364

5465
beforeEach(() => {
@@ -75,6 +86,15 @@ describe('Image Processing Integration', () => {
7586
},
7687
},
7788
};
89+
} else if (key === 'test-image.webp') {
90+
return {
91+
ContentType: 'image/webp',
92+
Body: {
93+
[Symbol.asyncIterator]: function* () {
94+
yield fs.readFileSync(path.join(fixturesDir, 'test-image.webp'));
95+
},
96+
},
97+
};
7898
} else if (key === 'animated.gif') {
7999
return {
80100
ContentType: 'image/gif',
@@ -369,4 +389,105 @@ describe('Image Processing Integration', () => {
369389
expect(lastS3ClientConfiguration.region).toBe('us-west-2');
370390
expect(lastS3GetObjectCommandInput.Bucket).toBe('my-test-bucket');
371391
});
392+
393+
test('should process WebP images as input format', async () => {
394+
const event = createCloudFrontEvent({
395+
uri: '/test-image.webp',
396+
region: 'us-west-2',
397+
bucket: 'my-test-bucket',
398+
});
399+
400+
const response = await handler(event);
401+
402+
expect(response.status).toBe('200');
403+
expect(response.bodyEncoding).toBe('base64');
404+
405+
const responseBuffer = Buffer.from(response.body, 'base64');
406+
const metadata = await sharp(responseBuffer).metadata();
407+
408+
expect(metadata.format).toBe('webp');
409+
expect(metadata.width).toBe(400);
410+
expect(metadata.height).toBe(300);
411+
412+
expect(lastS3ClientConfiguration.region).toBe('us-west-2');
413+
expect(lastS3GetObjectCommandInput.Bucket).toBe('my-test-bucket');
414+
});
415+
416+
test('should resize WebP images', async () => {
417+
const event = createCloudFrontEvent({
418+
uri: '/test-image.webp',
419+
querystring: 'width=200',
420+
region: 'us-west-2',
421+
bucket: 'my-test-bucket',
422+
});
423+
424+
const response = await handler(event);
425+
426+
expect(response.status).toBe('200');
427+
expect(response.bodyEncoding).toBe('base64');
428+
429+
const responseBuffer = Buffer.from(response.body, 'base64');
430+
const metadata = await sharp(responseBuffer).metadata();
431+
432+
expect(metadata.format).toBe('webp');
433+
expect(metadata.width).toBe(200);
434+
expect(metadata.height).toBe(150);
435+
436+
expect(lastS3ClientConfiguration.region).toBe('us-west-2');
437+
expect(lastS3GetObjectCommandInput.Bucket).toBe('my-test-bucket');
438+
});
439+
440+
test('should convert WebP to other formats', async () => {
441+
const event = createCloudFrontEvent({
442+
uri: '/test-image.webp',
443+
querystring: 'format=jpeg',
444+
region: 'us-west-2',
445+
bucket: 'my-test-bucket',
446+
});
447+
448+
const response = await handler(event);
449+
450+
expect(response.status).toBe('200');
451+
expect(response.bodyEncoding).toBe('base64');
452+
453+
expect(response.headers['content-type']).toEqual([
454+
{ key: 'Content-Type', value: 'image/jpeg' },
455+
]);
456+
457+
const responseBuffer = Buffer.from(response.body, 'base64');
458+
const metadata = await sharp(responseBuffer).metadata();
459+
460+
expect(metadata.format).toBe('jpeg');
461+
expect(metadata.width).toBe(400);
462+
expect(metadata.height).toBe(300);
463+
464+
expect(lastS3ClientConfiguration.region).toBe('us-west-2');
465+
expect(lastS3GetObjectCommandInput.Bucket).toBe('my-test-bucket');
466+
});
467+
468+
test('should resize and convert WebP images simultaneously', async () => {
469+
const event = createCloudFrontEvent({
470+
uri: '/test-image.webp',
471+
querystring: 'width=300&format=png',
472+
region: 'us-west-2',
473+
bucket: 'my-test-bucket',
474+
});
475+
476+
const response = await handler(event);
477+
478+
expect(response.status).toBe('200');
479+
expect(response.bodyEncoding).toBe('base64');
480+
481+
expect(response.headers['content-type']).toEqual([{ key: 'Content-Type', value: 'image/png' }]);
482+
483+
const responseBuffer = Buffer.from(response.body, 'base64');
484+
const metadata = await sharp(responseBuffer).metadata();
485+
486+
expect(metadata.format).toBe('png');
487+
expect(metadata.width).toBe(300);
488+
expect(metadata.height).toBe(225);
489+
490+
expect(lastS3ClientConfiguration.region).toBe('us-west-2');
491+
expect(lastS3GetObjectCommandInput.Bucket).toBe('my-test-bucket');
492+
});
372493
});

tests/image-processing.test.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,57 @@ describe('Image Processing Unit Tests', () => {
232232

233233
expect(response).toBe(originalResponse);
234234
});
235+
236+
test('should process WebP images as input format', async () => {
237+
const webpBuffer = Buffer.from('fake-webp-data');
238+
239+
mockS3Send.mockResolvedValueOnce({
240+
ContentType: 'image/webp',
241+
Body: {
242+
[Symbol.asyncIterator]: async function* () {
243+
yield webpBuffer;
244+
},
245+
},
246+
});
247+
248+
const event = createCloudFrontEvent({
249+
uri: '/test-image.webp',
250+
querystring: 'width=100',
251+
});
252+
253+
const response = await handler(event);
254+
255+
expect(response.status).toBe('200');
256+
expect(response.bodyEncoding).toBe('base64');
257+
expect(sharp().resize).toHaveBeenCalledWith({
258+
width: 100,
259+
height: null,
260+
fit: 'inside',
261+
withoutEnlargement: true,
262+
});
263+
});
264+
265+
test('should convert WebP input to different output format', async () => {
266+
const webpBuffer = Buffer.from('fake-webp-data');
267+
268+
mockS3Send.mockResolvedValueOnce({
269+
ContentType: 'image/webp',
270+
Body: {
271+
[Symbol.asyncIterator]: async function* () {
272+
yield webpBuffer;
273+
},
274+
},
275+
});
276+
277+
const event = createCloudFrontEvent({
278+
uri: '/test-image.webp',
279+
querystring: 'format=png',
280+
});
281+
282+
const response = await handler(event);
283+
284+
expect(response.status).toBe('200');
285+
expect(response.headers['content-type']).toEqual([{ key: 'Content-Type', value: 'image/png' }]);
286+
expect(sharp().png).toHaveBeenCalled();
287+
});
235288
});

0 commit comments

Comments
 (0)