如何使用SAM CLI部署API网关、Lambda(Node.js)和DynamoDB?

如何使用SAM CLI部署API网关、Lambda(Node.js)和DynamoDB?,node.js,aws-lambda,amazon-dynamodb,aws-api-gateway,serverless-application-model,Node.js,Aws Lambda,Amazon Dynamodb,Aws Api Gateway,Serverless Application Model,我正在尝试在本地系统中创建应用程序,并使用SAM CLI将其部署到AWS云。图中给出了该应用程序的基本轮廓 我已经为此应用程序创建了一个名为myproj的目录,所有子文件夹和文件如下图所示 template.yaml文件由以下代码组成- AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: myDB: Type: AWS::Serverless::Simpl

我正在尝试在本地系统中创建应用程序,并使用SAM CLI将其部署到AWS云。图中给出了该应用程序的基本轮廓

我已经为此应用程序创建了一个名为myproj的目录,所有子文件夹和文件如下图所示

template.yaml文件由以下代码组成-

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  myDB:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: tabmine
      PrimaryKey:
        Name: id
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
        
  LambdaWrite:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functionWrite/
      Handler: write.handler
      Runtime: nodejs12.x
      Events:
        apiForLambda:
          Type: Api 
          Properties:
            Path: /writedb
            Method: post
      Policies:
        DynamoDBWritePolicy:
          TableName: !Ref myDB
            
  LambdaRead:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functionRead/
      Handler: read.handler
      Runtime: nodejs12.x
      Events:
        apiForLambda:
          Type: Api 
          Properties:
            Path: /readdb
            Method: post
      Policies:
        DynamoDBReadPolicy:
          TableName: !Ref myDB
var AWS = require('aws-sdk');

var ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = function(event, context, callback) {
    var ID = event.id;
    
    var params = {
        TableName: 'tabmine',
        Key: {
            'id': ID
        }
    };
    
    ddb.get(params, callback);
    
};
functionRead文件夹中,package.json包含以下内容-

{
  "name": "myproj",
  "version": "1.0.0",
  "description": "",
  "main": "read.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.783.0"
  }
}

read.js文件包含以下代码-

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  myDB:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: tabmine
      PrimaryKey:
        Name: id
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
        
  LambdaWrite:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functionWrite/
      Handler: write.handler
      Runtime: nodejs12.x
      Events:
        apiForLambda:
          Type: Api 
          Properties:
            Path: /writedb
            Method: post
      Policies:
        DynamoDBWritePolicy:
          TableName: !Ref myDB
            
  LambdaRead:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functionRead/
      Handler: read.handler
      Runtime: nodejs12.x
      Events:
        apiForLambda:
          Type: Api 
          Properties:
            Path: /readdb
            Method: post
      Policies:
        DynamoDBReadPolicy:
          TableName: !Ref myDB
var AWS = require('aws-sdk');

var ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = function(event, context, callback) {
    var ID = event.id;
    
    var params = {
        TableName: 'tabmine',
        Key: {
            'id': ID
        }
    };
    
    ddb.get(params, callback);
    
};
functionWrite文件夹中,文件package.json包含以下内容-

{
  "name": "myproj",
  "version": "1.0.0",
  "description": "",
  "main": "write.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.783.0"
  }
}

var AWS = require('aws-sdk');

var ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = function(event, context, callback) {
    

    var ID = event.id;
    var NAME = event.name;
    
    var params = {
        TableName: 'tabmine',
        Item: {
            'id': ID,
            'name': NAME
        }
    };
    
    ddb.put(params, callback);
    
};
文件write.js包含以下内容-

{
  "name": "myproj",
  "version": "1.0.0",
  "description": "",
  "main": "write.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "aws-sdk": "^2.783.0"
  }
}

var AWS = require('aws-sdk');

var ddb = new AWS.DynamoDB.DocumentClient();

exports.handler = function(event, context, callback) {
    

    var ID = event.id;
    var NAME = event.name;
    
    var params = {
        TableName: 'tabmine',
        Item: {
            'id': ID,
            'name': NAME
        }
    };
    
    ddb.put(params, callback);
    
};
然后,我导航回终端中的myproj目录,并运行命令
sambuild
。 构建完成后,我运行命令
samdeploy--guided
,并按照步骤将堆栈部署到云中。然后,我检查了控制台,确认部署成功。 然后,在终端中,我运行了
curl-xpost-d'{“id”:“one”,“name”:“john”}'https://0000000000.execute-api.ap-south-1.amazonaws.com/Prod/writedb
。但是我得到了
{消息:“内部服务器错误”}

为了确认lambda和dynamoDB是否正确链接,我转到lambda控制台,为lambda函数创建了一个测试事件,该函数名为write.js,具有相同的负载
{id:“one”,“name:“john”}
。它成功运行并将这两项输入到dyanmoDB表中。类似地,我为lambda函数创建了另一个测试事件,其名称为read.js,负载为
{“id”:“one”}
。它还成功运行并显示了数据

为了确认API网关和lambda是否正确链接,我在API网关中对资源
/writedb
/readdb
运行了测试,但它给了我
{message:'Internal server Error'}


请帮助我解决此问题。

来自API网关调用的事件对象将具有以下结构-

{
  resource: '/func1',
  path: '/func1',
  httpMethod: 'POST',
  headers: {
    accept: '*/*',
    'content-type': 'application/x-www-form-urlencoded',
    Host: '0000000000.execute-api.ap-south-1.amazonaws.com',
    'User-Agent': 'curl/7.71.1',
    'X-Amzn-Trace-Id': 'Root=1-5fa018aa-60kdfkjsddd5f6c6c07a2',
    'X-Forwarded-For': '178.287.187.178',
    'X-Forwarded-Port': '443',
    'X-Forwarded-Proto': 'https'
  },
  multiValueHeaders: {
    accept: [ '*/*' ],
    'content-type': [ 'application/x-www-form-urlencoded' ],
    Host: [ '0000000000.execute-api.ap-south-1.amazonaws.com' ],
    'User-Agent': [ 'curl/7.71.1' ],
    'X-Amzn-Trace-Id': [ 'Root=1-5fa018aa-603d90fhgdhdgdjhj6c6dfda2' ],
    'X-Forwarded-For': [ '178.287.187.178' ],
    'X-Forwarded-Port': [ '443' ],
    'X-Forwarded-Proto': [ 'https' ]
  },
  queryStringParameters: null,
  multiValueQueryStringParameters: null,
  pathParameters: null,
  stageVariables: null,
  requestContext: {
    resourceId: 'scsu6k',
    resourcePath: '/func1',
    httpMethod: 'POST',
    extendedRequestId: 'VYjfdkjkjfjkfuA=',
    requestTime: '02/Nov/2020:14:33:14 +0000',
    path: '/test/func1',
    accountId: '00000000000',
    protocol: 'HTTP/1.1',
    stage: 'test',
    domainPrefix: 'f8h785q05a',
    requestTimeEpoch: 1604327594697,
    requestId: '459e0256-9c6f-4a24-bcf2-05520d6bc58a',
    identity: {
      cognitoIdentityPoolId: null,
      accountId: null,
      cognitoIdentityId: null,
      caller: null,
      sourceIp: '178.287.187.178',
      principalOrgId: null,
      accessKey: null,
      cognitoAuthenticationType: null,
      cognitoAuthenticationProvider: null,
      userArn: null,
      userAgent: 'curl/7.71.1',
      user: null
    },
    domainName: '000000000.execute-api.ap-south-1.amazonaws.com',
    apiId: 'lkjfslkfj'
  },
  body: '{"id":"1","name":"John"}',
  isBase64Encoded: false
}
从上面的JSON对象事件中,我们需要主体。因为主体是一个字符串,所以我们需要将其转换为JSON对象

因此,write.js应该修改为-

var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

exports.handler = async (event) => {
    try {
        
            //console.log(event);
            //console.log(event.body);
            var obj = JSON.parse(event.body);
        
            //console.log(obj.id);
            //console.log(obj.name);
        
            var ID = obj.id;
            var NAME = obj.name;
        
        
            var params = {
                TableName:'tabmine',
                Item: {
                 id : {S: ID}, 
                 name : {S: NAME}
                }
            
            };
        
            var data;
            var msg;
            
            try{
                data = await ddb.putItem(params).promise();
                console.log("Item entered successfully:", data);
                msg = 'Item entered successfully';
            } catch(err){
                console.log("Error: ", err);
                msg = err;
            }
        
        
            var response = {
                'statusCode': 200,
                'body': JSON.stringify({
                    message: msg
            })
        };
    } catch (err) {
        console.log(err);
        return err;
    }

    return response;
};
var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

exports.handler = async (event) => {
    try {
        
            //console.log(event);
            //console.log(event.body);
            var obj = JSON.parse(event.body);
        
            //console.log(obj.id);
            //console.log(obj.name);
        
            var ID = obj.id;
        
        
            var params = {
                TableName:'tabmine',
                Key: {
                 id : {S: ID}
                }
            
            };
        
            var data;
            
            try{
                data = await ddb.getItem(params).promise();
                console.log("Item read successfully:", data);
            } catch(err){
                console.log("Error: ", err);
                data = err;
            }
        
        
            var response = {
                'statusCode': 200,
                'body': JSON.stringify({
                    message: data
            })
        };
    } catch (err) {
        console.log(err);
        return err;
    }

    return response;
};
类似地,read.js将被修改为-

var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

exports.handler = async (event) => {
    try {
        
            //console.log(event);
            //console.log(event.body);
            var obj = JSON.parse(event.body);
        
            //console.log(obj.id);
            //console.log(obj.name);
        
            var ID = obj.id;
            var NAME = obj.name;
        
        
            var params = {
                TableName:'tabmine',
                Item: {
                 id : {S: ID}, 
                 name : {S: NAME}
                }
            
            };
        
            var data;
            var msg;
            
            try{
                data = await ddb.putItem(params).promise();
                console.log("Item entered successfully:", data);
                msg = 'Item entered successfully';
            } catch(err){
                console.log("Error: ", err);
                msg = err;
            }
        
        
            var response = {
                'statusCode': 200,
                'body': JSON.stringify({
                    message: msg
            })
        };
    } catch (err) {
        console.log(err);
        return err;
    }

    return response;
};
var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

exports.handler = async (event) => {
    try {
        
            //console.log(event);
            //console.log(event.body);
            var obj = JSON.parse(event.body);
        
            //console.log(obj.id);
            //console.log(obj.name);
        
            var ID = obj.id;
        
        
            var params = {
                TableName:'tabmine',
                Key: {
                 id : {S: ID}
                }
            
            };
        
            var data;
            
            try{
                data = await ddb.getItem(params).promise();
                console.log("Item read successfully:", data);
            } catch(err){
                console.log("Error: ", err);
                data = err;
            }
        
        
            var response = {
                'statusCode': 200,
                'body': JSON.stringify({
                    message: data
            })
        };
    } catch (err) {
        console.log(err);
        return err;
    }

    return response;
};

因此,这将解决问题。和template.yaml文件也是正确的。

我看不到您在模板中声明API网关的部分。yaml AWS::Serverless::API您能包括这一部分吗?否则,如何获得端点和阶段?根据AWS文档,AWS::Serverless::Api资源不需要显式添加到AWS Serverless应用程序定义模板中。此类型的资源是从模板中定义的AWS::Serverless::Function资源上定义的Api事件的联合隐式创建的,这些资源未引用AWS::Serverless::Api资源。见-。尽管我找到了解决这个问题的办法,我还是要写在答案里。谢谢你的关心。