1

我正在尝试在我的本地系统中创建一个应用程序并使用 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

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文件包含以下代码 -

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"
  }
}

并且文件write.js具有以下内容 -

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目录并运行命令sam build。构建完成后,我运行命令sam deploy --guided并按照步骤将堆栈部署到云端。然后,我检查了控制台以确认部署,并且成功。然后,在终端中,我跑了 curl -X POST -d '{"id":"one","name":"john"}' https://0000000000.execute-api.ap-south-1.amazonaws.com/Prod/writedb. 但我得到了{message : 'Internal server Error'}

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

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

请帮我解决这个问题。

4

1 回答 1

2

来自 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 对象事件中,我们需要body。由于 body 是一个字符串,所以我们需要将其转换为 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;
};

同样,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 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文件也是正确的。

于 2020-11-02T20:21:33.740 回答