使用 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 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容