如何解决Lambda Edge - 指定的键不存在
我使用 lambda 边缘来处理 Sharp 的图像压缩。该代码现在有效,但是当我尝试添加一个新函数来解析查询参数以让用户定义压缩质量时,Lambda/Cloudfront 开始通知我该键不存在,即使它确实存在。
用作示例的路径是:
/compress/480/uploads/1000491600869812260.jpg?quality=30
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>compress/480/uploads/1000491600869812260.jpg</Key>
<RequestId>5KPMBD6RNETZCA3Z</RequestId>
<HostId>
brMd/eCi6uv9s3VIl4IRHg7FlIytNA8DkgPjGfGrej4SkUsMxuEm1YHGEEll5rydO24gecIottE=
</HostId>
</Error>
来自 cloudfront 的错误日志:
#Version: 1.0
#Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version fle-status fle-encrypted-fields c-port time-to-first-byte x-edge-detailed-result-type sc-content-type sc-content-len sc-range-start sc-range-end
2021-06-09 06:06:43 ORD52-C3 689 182.253.36.23 GET d32xc09eirob59.cloudfront.net /compress/480/uploads/1000491600869812260.jpg 404 - Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/605.1.15%20(KHTML,%20like%20Gecko)%20Version/14.1.1%20Safari/605.1.15 quality=10 - Error FPFQE5Z-XuBeAK61KaJbNqDAbypyo3BhrH7xom7GZik--UgESIVQFw== d32xc09eirob59.cloudfront.net http 426 3.726 - - - Error HTTP/1.1 - - 54708 3.726 Error application/xml - - -
在下面的代码中,如果我注释调用函数来解析来自查询参数的质量的行(在代码中标记为“有问题的行”),代码将再次运行。但是,在我看来,代码没有任何问题,因为它是一个简单的正则表达式来获取值。
AWS lambda 中是否有任何限制或约束使其行为如此?有什么我可以做的事情吗?
附言我已经尝试使用 URL
和 querystring
库来解析路径,但它总是向我显示 LambdaException 错误,因此我尝试使用正则表达式手动解析它
有问题的线路/功能:
const getQuality = (path) => {
const match = path.match(/quality=(\d+)/)
const quality = parseInt(match[1],10)
return quality
}
const quality = getQuality(path)
完整代码:
'use strict'
const AWS = require('aws-sdk')
const S3 = new AWS.S3({ signatureversion: 'v4' })
const Sharp = require('sharp')
const BUCKET = 'some-bucket'
const QUALITY = 70
// Image types that can be handled by Sharp
const SUPPORTED_IMAGE_TYPES = ['jpg','jpeg','png','gif','webp','svg','tiff']
const JSON_CONTENT_HEADER = [{ key: 'Content-Type',value: 'application/json' }]
const WEBP_CONTENT_HEADER = [{ key: 'Content-Type',value: 'image/webp' }]
const getoriginalKey = (path) => {
const match = path.match(/\/(\d+)\/([A-Za-z0-9_\-]+)\/([A-Za-z0-9_\-]+)\.(\w+)\??/)
const imageWidth = parseInt(match[1],10)
const prefix = match[2]
const imageName = match[3]
const imageFormat = match[4]
const originalKey = `${prefix}/${imageName}.${imageFormat}`
return { originalKey,imageWidth,imageFormat }
}
const getQuality = (path) => {
const match = path.match(/quality=(\d+)/)
const quality = parseInt(match[1],10)
return quality
}
const responseUpdate = (
response,status,statusDescription,body,contentHeader,bodyEncoding = undefined
) => {
response.status = status
response.statusDescription = statusDescription
response.body = body
response.headers['content-type'] = contentHeader
if (bodyEncoding) {
response.bodyEncoding = bodyEncoding
}
return response
}
exports.handler = async (event,context,callback) => {
let { request,response } = event.Records[0].cf
const { uri } = request
const headers = response.headers
console.log(JSON.stringify({ status_code: response.status,uri }))
// NOTE: Check whether the image is present or not
if (response.status == 404) {
const splittedUri = uri.split('compress')
if (splittedUri.length != 2) {
callback(null,response)
return
}
// NOTE: Parse the prefix,image name,imageWidth and format
const path = splittedUri[1] // Read the required path (/480/uploads/123.jpg)
const { originalKey,imageFormat } = getoriginalKey(path)
if (!SUPPORTED_IMAGE_TYPES.some((type) => type == imageFormat.toLowerCase())) {
response = responseUpdate(
response,403,'Forbidden','Unsupported image type',JSON_CONTENT_HEADER
)
callback(null,response)
return
}
try {
// NOTE: Get original image from S3
const s3Object = await S3.getobject({ Bucket: BUCKET,Key: originalKey }).promise()
if (s3Object.ContentLength == 0) {
response = responseUpdate(
response,404,'Not Found','The image does not exist',JSON_CONTENT_HEADER
)
callback(null,response)
return
}
// NOTE: Optimize the image
let sharpObject = await Sharp(s3Object.Body)
const MetaData = await sharpObject.Metadata()
if (imageWidth < MetaData.width) {
sharpObject = await sharpObject.resize(imageWidth)
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// NOTE: The problematic line
const quality = getQuality(path)
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
const compressedImageBuffer = await sharpObject.webp({ quality: QUALITY }).toBuffer()
const byteLength = Buffer.byteLength(compressedImageBuffer,'base64')
if (byteLength == MetaData.size) {
callback(null,response)
return
}
if (byteLength >= 1046528) {
response = responseUpdate(
response,400,'Invalid size','The size of compressed image is too big',response)
return
}
// NOTE: Generate a binary response with an optimized image
response = responseUpdate(
response,200,'OK',compressedImageBuffer.toString('base64'),WEBP_CONTENT_HEADER,'base64'
)
response.headers['cache-control'] = [{ key: 'cache-control',value: 'max-age=31536000' }]
} catch (err) {
console.error(err)
}
} else {
headers['content-type'] = WEBP_CONTENT_HEADER
}
return response
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。