aws-lambda - Lambda Edge - 指定的键不存在
问题描述
我正在使用 lambda edge 来处理 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>
来自云端的错误日志:
#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 中是否有任何限制或约束使其行为如此?我能做些什么来让它发挥作用吗?
PS 我已经尝试使用
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, imageWidth, 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',
JSON_CONTENT_HEADER
)
callback(null, 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
}
解决方案
推荐阅读
- python-3.x - 用于 nuki smartlock 2.0 的 pynacl crypto_core_hsalsa20
- spring - 在 Webflux 中为 Content-Type 'multipart/form-data 返回 Mono 时出现 HttpMessageNotWritableException
- python - 用不均匀的numpy数组垂直填充熊猫数据框
- wxpython - 用 wxpython cairo 绘图感到困惑;wx.BufferedPaintDC 使笔触消失
- microservices - 如何在没有容器编排的情况下实现自动伸缩的微服务架构?
- amazon-web-services - AWS Elasticsearch 纵向扩展
- c++ - 请解释 C++ 中的 char* 返回类型
- python - 是否可以在 Spyder IDE 中编辑深色 UI 主题颜色?
- c++ - 将 Graphics.h 安装到代码块
- codenameone - 自定义 iOS VKB 工具栏