Skip to content

Commit 7f8b2a3

Browse files
authored
feat: First attempt to allow avif (BUZZ-2717) (aws-solutions#157)
* feat: First attempt to allow avif * fix: try to fix formatting * fix: add regex and error message * fix: add error text to test
1 parent 832dce6 commit 7f8b2a3

File tree

3 files changed

+65
-25
lines changed

3 files changed

+65
-25
lines changed

source/image-handler/image-request.js

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ class ImageRequest {
295295
parseRequestType(event) {
296296
const path = event["path"];
297297
const matchDefault = new RegExp(/^(\/?)([0-9a-zA-Z+\/]{4})*(([0-9a-zA-Z+\/]{2}==)|([0-9a-zA-Z+\/]{3}=))?$/);
298-
const matchThumbor = new RegExp(/^(\/?)((fit-in)?|(filters:.+\(.?\))?|(unsafe)?).*(\.+jpg|\.+png|\.+webp|\.tiff|\.jpeg|\.svg|\.gif)$/i);
299-
const matchCustom = new RegExp(/(\/?)(.*)(jpg|png|webp|tiff|jpeg|svg|gif)/i);
298+
const matchThumbor = new RegExp(/^(\/?)((fit-in)?|(filters:.+\(.?\))?|(unsafe)?).*(\.+jpg|\.+png|\.+webp|\.tiff|\.jpeg|\.svg|\.gif|\.avif)$/i);
299+
const matchCustom = new RegExp(/(\/?)(.*)(jpg|png|webp|tiff|jpeg|svg|gif|avif)/i);
300300

301301
const definedEnvironmentVariables =
302302
process.env.REWRITE_MATCH_PATTERN !== "" &&
@@ -326,7 +326,7 @@ class ImageRequest {
326326
status: 400,
327327
code: "RequestTypeError",
328328
message:
329-
"The type of request you are making could not be processed. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg, gif) and that your image request is provided in the correct syntax. Refer to the documentation for additional guidance on forming image requests."
329+
"The type of request you are making could not be processed. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg, gif, avif) and that your image request is provided in the correct syntax. Refer to the documentation for additional guidance on forming image requests."
330330
};
331331
}
332332
}
@@ -406,11 +406,14 @@ class ImageRequest {
406406
*/
407407
getOutputFormat(event) {
408408
const autoWebP = process.env.AUTO_WEBP;
409+
const autoAvif = process.env.AUTO_AVIF;
409410
let accept = event.headers
410411
? event.headers.Accept || event.headers.accept
411412
: [];
412413
if (autoWebP === "Yes" && accept && accept.includes("image/webp")) {
413414
return "webp";
415+
} else if (autoAvif === "Yes" && accept && accept.includes("image/avif")) {
416+
return "avif";
414417
} else if (this.requestType === "Default") {
415418
const decoded = this.decodeRequest(event);
416419
return decoded.outputFormat;
@@ -423,33 +426,34 @@ class ImageRequest {
423426
* Return the output format depending on first four hex values of an image file.
424427
* @param {Buffer} imageBuffer - Image buffer.
425428
*/
426-
inferImageType(imageBuffer) {
427-
switch (imageBuffer.toString('hex').substring(0, 8).toUpperCase()) {
428-
case '89504E47':
429-
return 'image/png';
430-
case 'FFD8FFDB':
431-
return 'image/jpeg';
432-
case 'FFD8FFE0':
433-
return 'image/jpeg';
434-
case 'FFD8FFEE':
435-
return 'image/jpeg';
436-
case 'FFD8FFE1':
437-
return 'image/jpeg';
438-
case '52494646':
439-
return 'image/webp';
440-
case '49492A00':
441-
return 'image/tiff';
442-
case '4D4D002A':
443-
return 'image/tiff';
429+
inferImageType(imageBuffer) {
430+
switch (imageBuffer.toString("hex").substring(0, 8).toUpperCase()) {
431+
case "89504E47":
432+
return "image/png";
433+
case "FFD8FFDB":
434+
return "image/jpeg";
435+
case "FFD8FFE0":
436+
return "image/jpeg";
437+
case "FFD8FFEE":
438+
return "image/jpeg";
439+
case "FFD8FFE1":
440+
return "image/jpeg";
441+
case "52494646":
442+
return "image/webp";
443+
case "49492A00":
444+
return "image/tiff";
445+
case "4D4D002A":
446+
return "image/tiff";
444447
default:
445448
throw {
446449
status: 500,
447-
code: 'RequestTypeError',
448-
message: 'The file does not have an extension and the file type could not be inferred. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg). Refer to the documentation for additional guidance on forming image requests.'
450+
code: "RequestTypeError",
451+
message:
452+
"The file does not have an extension and the file type could not be inferred. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg, avif). Refer to the documentation for additional guidance on forming image requests.",
449453
};
450454
}
451455
}
452456
}
453457

454458
// Exports
455-
module.exports = ImageRequest;
459+
module.exports = ImageRequest;

source/image-handler/terraform/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ module "lambda" {
5656
environment = {
5757
variables = {
5858
AUTO_WEBP = "Yes"
59+
AUTO_AVIF = "Yes"
5960
CORS_ENABLED = "Yes"
6061
CORS_ORIGIN = "*"
6162
SOURCE_BUCKETS = aws_s3_bucket.images.bucket

source/image-handler/test/image-request.spec.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ describe('parseRequestType()', function () {
975975
expect(error).toEqual({
976976
status: 400,
977977
code: 'RequestTypeError',
978-
message: 'The type of request you are making could not be processed. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg, gif) and that your image request is provided in the correct syntax. Refer to the documentation for additional guidance on forming image requests.'
978+
message: 'The type of request you are making could not be processed. Please ensure that your original image is of a supported file type (jpg, png, tiff, webp, svg, gif, avif) and that your image request is provided in the correct syntax. Refer to the documentation for additional guidance on forming image requests.'
979979
});
980980
}
981981
});
@@ -1197,4 +1197,39 @@ describe('getOutputFormat()', function () {
11971197
expect(result).toEqual(null);
11981198
});
11991199
});
1200+
describe("003/AutoAVIFDisabled", function () {
1201+
it("Should pass if it returns null when AUTO_AVIF is disabled with accepts header including avif", function () {
1202+
// Arrange
1203+
process.env = {
1204+
AUTO_AVIF: "No",
1205+
};
1206+
const event = {
1207+
headers: {
1208+
Accept:
1209+
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
1210+
},
1211+
};
1212+
// Act
1213+
const imageRequest = new ImageRequest(s3, secretsManager);
1214+
const result = imageRequest.getOutputFormat(event);
1215+
// Assert
1216+
expect(result).toEqual(null);
1217+
});
1218+
});
1219+
describe("004/AutoAVIFUnset", function () {
1220+
it("Should pass if it returns null when AUTO_AVIF is not set with accepts header including avif", function () {
1221+
// Arrange
1222+
const event = {
1223+
headers: {
1224+
Accept:
1225+
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
1226+
},
1227+
};
1228+
// Act
1229+
const imageRequest = new ImageRequest(s3, secretsManager);
1230+
const result = imageRequest.getOutputFormat(event);
1231+
// Assert
1232+
expect(result).toEqual(null);
1233+
});
1234+
});
12001235
});

0 commit comments

Comments
 (0)