21

采用这种方法的动机首先来自亚马逊:https ://aws.amazon.com/blogs/compute/resize-images-on-the-fly-with-amazon-s3-aws-lambda-and-amazon -api-gateway/(在他们添加“更新”之前......)

在我们的 AWS Lambda 调整大小函数中,它调整图像的大小并将新图像存储在 S3 上。

const s3_bucket = process.env.s3_bucket;
S3.putObject({
  Body: buffer,
  Bucket: s3_bucket,
  ContentType: contentType,
  CacheControl: 'max-age=31536000',
  Key: key,
  StorageClass: 'STANDARD'
}).promise()

现在我们希望它适用于我们所有的测试/登台环境以及生产环境。所以我找到了“环境变量”,我虽然很棒!但是当我尝试部署一个新版本时,我得到的只是:

不支持环境变量

我们是否在 CloudFront 中设置错误?我们使用的是 Node 6.10 版本。我很难相信我们是否必须对存储桶进行硬编码并保留不同版本的代码来处理这个问题?如果是这样的话,那么我们在使用 AWS Lambda 上浪费了很多时间......

编辑:我们所做的是请求图像,如“media/catalog/product/3/0/30123/768x/lorem.jpg”,然后我们使用位于“media/catalog/product/3/”的原始图像0/30123.jpg”,如果浏览器支持,将其调整为 768px 和 webp,然后返回新图像(如果尚未缓存)。

4

6 回答 6

34

使用自定义来源标头的解决方法

Lambda@Edge 不支持环境变量,如限制文档中所述

但是,如果您在源请求或源响应中使用 Lambda@Edge,则可以使用CloudFront Origin Custom Headers的解决方法。

基本上,您可以在 CloudFront 源中设置自定义标头,而不是环境变量。然后,这些“静态”标头将传递给您的原始请求/响应 Lambda@Edge。

在此处输入图像描述

然后您可以通过以下方式在您的 Lambda@Edge 函数代码中访问它们:

const foo = request.origin.custom.customHeaders["x-env-foo"][0].value;

或者当使用 S3 作为原点时:

const foo = request.origin.s3.customHeaders["x-env-foo"][0].value;

另请参阅https://medium.com/@mnylen/lambda-edge-gotchas-and-tips-93083f8b4152

于 2019-09-25T15:06:14.680 回答
4

作为所选答案的替代...

使用Serverless FrameworkWebpackserverless-webpack插件也可以实现同样的目的。

您可以通过以下方式访问用于无服务器操作的选项:

const slsw = require('serverless-webpack');
const stage = slsw.lib.options.stage;

或者,您可以通过以下方式访问serverless.yml文件中的信息:

const serverless = slsw.lib.serverless;

然后只需将其添加到文件的插件中webpack.config.js

plugins: [new EnvironmentPlugin({ VAR1: var1, VAR2: var2, STAGE: stage })]

此方法可以为您提供一种在 Lambda@Edge 函数中管理环境变量的简单方法 - 阅读案例研究以了解无服务器框架为何如此出色。

于 2020-05-08T11:21:02.427 回答
3

使用 lambda 函数名称的解决方法

您还可以检查process.env.AWS_LAMBDA_FUNCTION_NAME您的开发/产品是否有单独的功能。

const getIsDev = () => {
    // lambda at edges cant set environment variables in the console.
    if (!process.env.AWS_LAMBDA_FUNCTION_NAME) {
        return true // << double check this is the behavior you want to fall back to.
    }
    if (process.env.AWS_LAMBDA_FUNCTION_NAME.indexOf("-dev") => 0) {
        // does the function name contain the word -dev?  
        return true
    }
    return false
}
于 2021-02-03T21:30:26.120 回答
2

如本文档中提到的 CloudFront Lambda 限制:

不支持环境变量。

您可以做的是使用 SSM Parameter Store 来管理函数的变量。您可以通过控制台或以编程方式编辑 Parameter Store 变量,您可以使用ssm.getParameter() 函数获取变量

于 2019-02-22T14:22:22.027 回答
1

我将此作为评论,但我认为值得将其添加为答案。

为什么需要先使用 Lambda@Edge?我理解您的沮丧,但 Lambda@Edge 旨在实现一组完全不同的事情。在此处查看一些用例

在您的使用案例中,您将对象上传到 S3,PUT 对象事件将触发您的 Lambda 函数,该函数本质上是异步且最终一致的。您的用户真的不需要优化的缩略图生成执行时间,因为无论如何您只会获得几百毫秒。当他们需要缩略图时,无论如何它已经在那里了。

在常规的 Lambda 函数中,您绝对可以使用环境变量,从而非常容易地将不同的设置应用于不同的环境(开发、测试、生产)。

您可以在此处查看如何在常规 Lambda 函数中设置环境变量

于 2019-02-22T14:44:35.937 回答
1

我通过s3_bucket在 bash 构建脚本中添加到 js 文件来解决它。所以我指定build.sh [s3_bucket] [environment-name]

if [ ! $# -eq 2 ]; then
    echo 'You need to provide two parameters: [s3_bucket] [environment]'
    echo 'example: build.sh imagetest-us-east-1 next'
    echo 'example: build.sh [s3_bucket_to_be_defined] production'
    exit 1
fi

filename='index.js'
setCurrentEnvironment() {
    jsEnv="const s3_bucket='$1';"
    mv "$filename" "$filename".orig && cp "$filename".orig "$filename"
    echo -e "$jsEnv\n\n$(cat ${filename})" > "$filename"
}
restoreDefault() {
    rm -rf "$filename"
    mv "$filename".orig "$filename"
}

setCurrentEnvironment $1
zip -FS -q -r "../../dist/resize__$2.zip" *
restoreDefault
于 2019-03-08T13:22:20.100 回答