Skip to content

Commit

Permalink
feat: First attempt to allow avif (BUZZ-2717) (aws-solutions#157)
Browse files Browse the repository at this point in the history
* feat: First attempt to allow avif

* fix: try to fix formatting

* fix: add regex and error message

* fix: add error text to test
  • Loading branch information
TimSusa authored Aug 11, 2022
1 parent 832dce6 commit 7f8b2a3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 25 deletions.
52 changes: 28 additions & 24 deletions source/image-handler/image-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ class ImageRequest {
parseRequestType(event) {
const path = event["path"];
const matchDefault = new RegExp(/^(\/?)([0-9a-zA-Z+\/]{4})*(([0-9a-zA-Z+\/]{2}==)|([0-9a-zA-Z+\/]{3}=))?$/);
const matchThumbor = new RegExp(/^(\/?)((fit-in)?|(filters:.+\(.?\))?|(unsafe)?).*(\.+jpg|\.+png|\.+webp|\.tiff|\.jpeg|\.svg|\.gif)$/i);
const matchCustom = new RegExp(/(\/?)(.*)(jpg|png|webp|tiff|jpeg|svg|gif)/i);
const matchThumbor = new RegExp(/^(\/?)((fit-in)?|(filters:.+\(.?\))?|(unsafe)?).*(\.+jpg|\.+png|\.+webp|\.tiff|\.jpeg|\.svg|\.gif|\.avif)$/i);
const matchCustom = new RegExp(/(\/?)(.*)(jpg|png|webp|tiff|jpeg|svg|gif|avif)/i);

const definedEnvironmentVariables =
process.env.REWRITE_MATCH_PATTERN !== "" &&
Expand Down Expand Up @@ -326,7 +326,7 @@ class ImageRequest {
status: 400,
code: "RequestTypeError",
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."
"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."
};
}
}
Expand Down Expand Up @@ -406,11 +406,14 @@ class ImageRequest {
*/
getOutputFormat(event) {
const autoWebP = process.env.AUTO_WEBP;
const autoAvif = process.env.AUTO_AVIF;
let accept = event.headers
? event.headers.Accept || event.headers.accept
: [];
if (autoWebP === "Yes" && accept && accept.includes("image/webp")) {
return "webp";
} else if (autoAvif === "Yes" && accept && accept.includes("image/avif")) {
return "avif";
} else if (this.requestType === "Default") {
const decoded = this.decodeRequest(event);
return decoded.outputFormat;
Expand All @@ -423,33 +426,34 @@ class ImageRequest {
* Return the output format depending on first four hex values of an image file.
* @param {Buffer} imageBuffer - Image buffer.
*/
inferImageType(imageBuffer) {
switch (imageBuffer.toString('hex').substring(0, 8).toUpperCase()) {
case '89504E47':
return 'image/png';
case 'FFD8FFDB':
return 'image/jpeg';
case 'FFD8FFE0':
return 'image/jpeg';
case 'FFD8FFEE':
return 'image/jpeg';
case 'FFD8FFE1':
return 'image/jpeg';
case '52494646':
return 'image/webp';
case '49492A00':
return 'image/tiff';
case '4D4D002A':
return 'image/tiff';
inferImageType(imageBuffer) {
switch (imageBuffer.toString("hex").substring(0, 8).toUpperCase()) {
case "89504E47":
return "image/png";
case "FFD8FFDB":
return "image/jpeg";
case "FFD8FFE0":
return "image/jpeg";
case "FFD8FFEE":
return "image/jpeg";
case "FFD8FFE1":
return "image/jpeg";
case "52494646":
return "image/webp";
case "49492A00":
return "image/tiff";
case "4D4D002A":
return "image/tiff";
default:
throw {
status: 500,
code: 'RequestTypeError',
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.'
code: "RequestTypeError",
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, avif). Refer to the documentation for additional guidance on forming image requests.",
};
}
}
}

// Exports
module.exports = ImageRequest;
module.exports = ImageRequest;
1 change: 1 addition & 0 deletions source/image-handler/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ module "lambda" {
environment = {
variables = {
AUTO_WEBP = "Yes"
AUTO_AVIF = "Yes"
CORS_ENABLED = "Yes"
CORS_ORIGIN = "*"
SOURCE_BUCKETS = aws_s3_bucket.images.bucket
Expand Down
37 changes: 36 additions & 1 deletion source/image-handler/test/image-request.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ describe('parseRequestType()', function () {
expect(error).toEqual({
status: 400,
code: 'RequestTypeError',
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.'
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.'
});
}
});
Expand Down Expand Up @@ -1197,4 +1197,39 @@ describe('getOutputFormat()', function () {
expect(result).toEqual(null);
});
});
describe("003/AutoAVIFDisabled", function () {
it("Should pass if it returns null when AUTO_AVIF is disabled with accepts header including avif", function () {
// Arrange
process.env = {
AUTO_AVIF: "No",
};
const event = {
headers: {
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
},
};
// Act
const imageRequest = new ImageRequest(s3, secretsManager);
const result = imageRequest.getOutputFormat(event);
// Assert
expect(result).toEqual(null);
});
});
describe("004/AutoAVIFUnset", function () {
it("Should pass if it returns null when AUTO_AVIF is not set with accepts header including avif", function () {
// Arrange
const event = {
headers: {
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
},
};
// Act
const imageRequest = new ImageRequest(s3, secretsManager);
const result = imageRequest.getOutputFormat(event);
// Assert
expect(result).toEqual(null);
});
});
});

0 comments on commit 7f8b2a3

Please sign in to comment.