diff --git a/source/image-handler/image-handler.ts b/source/image-handler/image-handler.ts index 82cd67937..6f63b6e3c 100644 --- a/source/image-handler/image-handler.ts +++ b/source/image-handler/image-handler.ts @@ -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 { 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 diff --git a/source/image-handler/image-request.ts b/source/image-handler/image-request.ts index 06ac23cf3..90b47aa2e 100644 --- a/source/image-handler/image-request.ts +++ b/source/image-handler/image-request.ts @@ -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) diff --git a/source/image-handler/index.ts b/source/image-handler/index.ts index 1acfee867..8b76be163 100755 --- a/source/image-handler/index.ts +++ b/source/image-handler/index.ts @@ -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(); @@ -50,7 +50,7 @@ export async function handler(event: ImageHandlerEvent): Promise { // Arrange @@ -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(() => ({