-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
98 lines (81 loc) · 2.84 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const {
S3Client,
WriteGetObjectResponseCommand,
} = require("@aws-sdk/client-s3");
const axios = require("axios");
const sharp = require("sharp");
const s3 = new S3Client();
const DEFAULT_QUALITY = parseInt(process.env.DEFAULT_QUALITY) || 85;
const DEFAULT_CONTENT_TYPE = process.env.DEFAULT_CONTENT_TYPE || "image/webp";
exports.handler = async (event) => {
const { outputRoute, outputToken, inputS3Url } = event.getObjectContext;
const userRequestUrl = event.userRequest.url;
const queryParams = new URLSearchParams(new URL(userRequestUrl).search);
try {
const { data, headers } = await fetchImage(inputS3Url);
const originContentType = headers["content-type"] || DEFAULT_CONTENT_TYPE;
const transformedImage = await processResize(data, queryParams);
await sendResponse(
transformedImage,
originContentType,
outputRoute,
outputToken
);
} catch (err) {
logError("An error occurred while processing the image", err);
return {
statusCode: 500,
body: "Image processing failed",
};
}
};
const fetchImage = async (url) => {
try {
return await axios.get(url, { responseType: "arraybuffer" });
} catch (err) {
throw new Error(`Failed to fetch image from S3: ${err.message}`);
}
};
const processResize = async (originImage, queryParams) => {
const image = sharp(originImage);
const { format } = await image.metadata();
const width = parseInt(queryParams.get("w")) || null;
const height = parseInt(queryParams.get("h")) || null;
const quality = parseInt(queryParams.get("q")) || null;
if (!width && !height && !quality) return originImage;
return await formatImage(image, format, width, height, quality);
};
const formatImage = async (image, format, width, height, quality) => {
quality = clamp(quality, 1, 100);
switch (format) {
case "jpeg":
return await image.resize(width, height).jpeg({ quality }).toBuffer();
case "png":
return await image.resize(width, height).png({ quality }).toBuffer();
case "webp":
return await image.resize(width, height).webp({ quality }).toBuffer();
default:
return await image.resize(width, height).toBuffer();
}
};
const sendResponse = async (body, contentType, requestRoute, requestToken) => {
try {
const writeResponseParams = {
RequestRoute: requestRoute,
RequestToken: requestToken,
Body: body,
StatusCode: 200,
Headers: { "Content-Type": contentType },
};
await s3.send(new WriteGetObjectResponseCommand(writeResponseParams));
} catch (err) {
throw new Error(`Failed to send response: ${err.message}`);
}
};
const clamp = (value, min, max) => {
if (!value) return DEFAULT_QUALITY;
return Math.max(min, Math.min(value, max));
};
const logError = (message, err) => {
console.error(`\n| >> MESSAGE: ${message}\n| >> ERROR_DETAILS: ${err}`);
};