Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion source/image-handler/image-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,27 @@ export class ImageHandler {
/**
* Main method for processing image requests and outputting modified images.
* @param imageRequestInfo An image request.
* @returns Processed and modified image encoded as base64 string.
* @returns Processed and modified image encoded as base64 string. or json object if outputFormat is JSON
*/
async process(imageRequestInfo: ImageRequestInfo): Promise<string> {
const { originalImage, edits } = imageRequestInfo;
const options = { failOnError: false, animated: imageRequestInfo.contentType === ContentTypes.GIF };
let base64EncodedImage = "";

if (imageRequestInfo.outputFormat === ImageFormatTypes.JSON) {
const metadata = await sharp(originalImage, options).metadata();

const filteredMetadata = Object.keys(metadata).reduce((acc, key) => {
if (!Buffer.isBuffer(metadata[key])) {
acc[key] = metadata[key];
}
return acc;
}, {});

return JSON.stringify(filteredMetadata);

}

// Apply edits if specified
if (edits && Object.keys(edits).length) {
// convert image to Sharp object
Expand Down
5 changes: 4 additions & 1 deletion source/image-handler/image-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ export class ImageRequest {
ImageFormatTypes.TIFF,
ImageFormatTypes.HEIF,
ImageFormatTypes.GIF,
ImageFormatTypes.JSON,
];

imageRequestInfo.contentType = `image/${imageRequestInfo.outputFormat}`;

imageRequestInfo.contentType = imageRequestInfo.outputFormat === ImageFormatTypes.JSON? 'application/json' : `image/${imageRequestInfo.outputFormat}`;

if (
requestType.includes(imageRequestInfo.requestType) &&
acceptedValues.includes(imageRequestInfo.outputFormat)
Expand Down
4 changes: 2 additions & 2 deletions source/image-handler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getOptions } from "../solution-utils/get-options";
import { isNullOrWhiteSpace } from "../solution-utils/helpers";
import { ImageHandler } from "./image-handler";
import { ImageRequest } from "./image-request";
import { Headers, ImageHandlerEvent, ImageHandlerExecutionResult, StatusCodes } from "./lib";
import { Headers, ImageFormatTypes, ImageHandlerEvent, ImageHandlerExecutionResult, StatusCodes } from "./lib";
import { SecretProvider } from "./secret-provider";

const awsSdkOptions = getOptions();
Expand Down Expand Up @@ -50,7 +50,7 @@ export async function handler(event: ImageHandlerEvent): Promise<ImageHandlerExe

return {
statusCode: StatusCodes.OK,
isBase64Encoded: true,
isBase64Encoded: imageRequestInfo.outputFormat === ImageFormatTypes.JSON ? false : true,
headers,
body: processedRequest,
};
Expand Down
1 change: 1 addition & 0 deletions source/image-handler/lib/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export enum ImageFormatTypes {
HEIC = "heic",
RAW = "raw",
GIF = "gif",
JSON = "json",
}

export enum ImageFitTypes {
Expand Down
2 changes: 1 addition & 1 deletion source/image-handler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"scripts": {
"clean": "rm -rf node_modules/ dist/ coverage/",
"pretest": "npm run clean && npm ci",
"test": "jest --coverage --silent"
"test": "jest --watch"
},
"dependencies": {
"aws-sdk": "^2.1477.0",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions source/image-handler/test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import fs from "fs";

import { mockAwsS3 } from "./mock";

import { handler } from "../index";
import { ImageHandlerError, ImageHandlerEvent, StatusCodes } from "../lib";
import sharp from "sharp";

describe("index", () => {
// Arrange
Expand Down Expand Up @@ -47,6 +50,59 @@ describe("index", () => {
expect(result).toEqual(expectedResult);
});

it.only("should return a json with metadata when outputFormat='json'", async () => {
const originalImage = fs.readFileSync("./test/image/orientation-example.jpg");
const image = sharp(originalImage, { failOnError: false }).withMetadata();
const buffer = await image.toBuffer();

// Mock
mockAwsS3.getObject.mockImplementationOnce(() => ({
promise() {
return Promise.resolve({ Body: Buffer.from(buffer), ContentType: "image/jpeg" });
},
}));
// Arrange

const event: ImageHandlerEvent = {
path: btoa(JSON.stringify({ bucket: "source-bucket", key: "test.jpg", outputFormat: "json" })),
};

// Act
const result = await handler(event);

const expectedBody = {
format: "jpeg",
size: 867153,
width: 2316,
height: 3088,
}

expect(JSON.parse(result.body)).toEqual(expect.objectContaining(expectedBody));

const expectedResult = {
statusCode: StatusCodes.OK,
isBase64Encoded: true,
headers: {
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Credentials": true,
"Content-Type": "application/json",
Expires: undefined,
"Cache-Control": "max-age=31536000,public",
"Last-Modified": undefined,
},
};

delete result.body;

// Assert
expect(mockAwsS3.getObject).toHaveBeenCalledWith({
Bucket: "source-bucket",
Key: "test.jpg",
});
expect(result).toEqual(expectedResult);
});

it("should return the image with custom headers when custom headers are provided", async () => {
// Mock
mockAwsS3.getObject.mockImplementationOnce(() => ({
Expand Down