使用 Node.js AWS 开发工具包将函数部署到 Lambda

Nodejs AWS API 有一个用于在 Lambda 上部署函数的。通过一些工作,您可以使用 适用于 Node.js 的 AWS 开发工具包。以下是您可以通过 3 个步骤上传和运行 Lambda 函数的方法:

1. 将函数包上传到 S3

不幸的是,AWS API 要求您将捆绑的 Lambda 函数存储为 .zip S3 上的文件,并且该 S3 存储桶需要与 AWS 区域 您的 Lambda 函数

您可以在此处阅读有关 在 Node.js 中将对象上传到 S3 的 。 这里是精简版。

首先,假设你有一个简单的 test.js 包含一个文件 handler 功能:

exports.handler = async function(event, context) {
  return { statusCode: 200, body: Hello, World };
};

Lambda 将为您执行此函数并返回 Hello World。但首先,您需要将其存档 test.js 归档到一个 .zip 文件并将其上传到 S3。 要捆绑 zip 文件,您可以使用 npm 上的 adm-zip 包

const AdmZip = require(adm-zip);
const AWS = require(aws-sdk);

const file = new AdmZip();
file.addFile(test.js, Buffer.from(`
  exports.handler = async function(event, context) {
    return { statusCode: 200, body: Hello, World };
  };
`));

file.writeZip(./test.zip);

// Make sure the configs are set!
AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: us-east-1
});

const s3 = new AWS.S3();
await new Promise((resolve, reject) => {
  s3.upload({
    Bucket: awsBucket, // Make this your AWS bucket
    Body: fs.createReadStream(./test.zip),
    Key: test.zip
  }, (err, data) => err == null ? resolve(data) : reject(err));
});

2. 创建 Lambda 函数

现在文件位于 S3 上,您可以创建一个 Lambda 函数 使用 AWS.Lambda() 帮手:

const AWS = require(aws-sdk);
const promisify = require(util).promisify;

AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: us-east-1
});

const lambda = new AWS.Lambda();

// Actually create the function with the given name and runtime.
const opts = {
  FunctionName: nodetest,
  Runtime: nodejs12.x,
  // Whatever role, doesnt matter
  Role: add actual role that starts with `arn:aws:iam::` here,
  // `test` is for `test.js`, and `handler` is for `exports.handler`.
  Handler: test.handler,
  Code: {
    S3Bucket: awsBucket,
    S3Key: test.zip
  }
};
const fn = await promisify(lambda.createFunction).call(lambda, opts);
functionArn = fn.FunctionArn; // The id of the lambda function

// Let API Gateway call this Lambda function
await promisify(lambda.addPermission).call(lambda, {
  FunctionName: nodetest,
  StatementId: doesntmatter,
  Action: lambda:InvokeFunction,
  Principal: apigateway.amazonaws.com
});

const res = await promisify(lambda.invoke).call(lambda, {
  FunctionName: nodetest
});
res.Payload; // {statusCode:200,body:Hello, World}

为方便起见,上述代码使用了 Node.js util.promisify() 助手,因为 AWS 开发工具包目前不支持承诺。学习更多关于 util.promisify() 在这里

3.创建 API 网关通过 HTTP 访问函数

所以现在您有了一个可以通过 AWS 开发工具包调用的 Lambda 函数。 但是通过 HTTP 调用它呢? 这就是您需要 AWS API Gateway API 的目的。 您需要 创建一个新的 REST API 并向 其添加集成

一步一步,你需要:

  1. 创建新的 REST API
  2. 向 REST API 添加资源
  3. 添加一个 GET资源方法
  4. 挂钩 GET调用 Lambda 的方法

这是完整的脚本:

this.timeout(5000);
const AWS = require(aws-sdk);
const promisify = require(util).promisify;

AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: us-east-1
});

const gateway = new AWS.APIGateway();

// Create a new API
const api = await promisify(gateway.createRestApi).call(gateway, {
  name: My Test API
});
const restApiId = api.id;

// Create a new endpoint (resource) at `/test/
const resources = await promisify(gateway.getResources).call(gateway, { restApiId });
const resource = await promisify(gateway.createResource).call(gateway, {
  restApiId,
  // Parent resource is the root resource
  parentId: resources.items[0].id,
  pathPart: test
});
await promisify(gateway.putMethod).call(gateway, {
  restApiId,
  resourceId: resource.id,
  httpMethod: GET,
  authorizationType: NONE
});

// Configure the endpoint to use the Lambda function
await promisify(gateway.putIntegration).call(gateway, {
  restApiId,
  resourceId: resource.id,
  httpMethod: GET,
  integrationHttpMethod: POST,
  type: AWS_PROXY,
  uri: `arn:aws:apigateway:us-east-1:lambda:path//2015-03-31/functions/${functionArn}/invocations`
});
await promisify(gateway.createDeployment).call(gateway, { restApiId, stageName: prod });

await promisify(gateway.putMethodResponse).call(gateway, {
  restApiId,
  resourceId: resource.id,
  httpMethod: GET,
  statusCode: 200
});
await promisify(gateway.putIntegrationResponse).call(gateway, {
  restApiId,
  resourceId: resource.id,
  httpMethod: GET,
  statusCode: 200
});

// Now call the function using Axios!
const axios = require(axios);

const res = await axios.get(`https://${api.id}.execute-api.us-east-1.amazonaws.com/prod/test`);
res.data; // Hello, World
© 版权声明
THE END
喜欢就支持一下吧
点赞214 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容