我尝试通过API Gateway和用Javascript(ES6格式)编写的Lambda函数向DynamoDB发送扫描命令。每次我这样做时,我都会收到403错误:无法满足请求。我已将aws-sdk依赖项放入Lambda层。
Lambda函数:
import { DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";
import { unmarshall } from '@aws-sdk/util-dynamodb';
const REGION = process.env.AWS_REGION;
const dynamo = new DynamoDBClient({region: REGION});
const tableName = process.env.MOVIE_TABLE;
//get table name from MOVIE_TABLE environment variable
/**
*
* Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
* @param {Object} event - API Gateway Lambda Proxy Input Format
*
* Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
* @param {Object} context
*
* Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
* @returns {Object} object - API Gateway Lambda Proxy Output Format
*
*/
//test with command: sam local start-api --port 8080 --log-file logfile.txt
export const lambdaHandler = async (event, context) => {
let respBody;
let sCode = 200;
if (event.httpMethod !== 'GET') {
throw new Error(`GET method only accepts GET method, you tried: ${event.httpMethod}`);
}
//All log statements are written to CloudWatch
console.info('received request for get:', event);
console.info('received context:', context);
try {
const params = {
TableName: tableName,
};
const command = new ScanCommand(params);
console.info(`params Tablename: ${params.TableName}`);
console.info(`Region: ${REGION}`);
respBody = await dynamo.send(command);
respBody = respBody.Items;
respBody = respBody.map((i) => unmarshall(i));
} catch (err) {
sCode = err.statusCode;
respBody = err.message;
var stack = err.stack;
//const { requestId, cfId, extendedRequestId } = err.$$metadata;
console.info('Error stacktrace: \n');
console.info(stack);
//console.info('Error metdata: \n');
//console.log({ requestId, cfId, extendedRequestId });
} finally {
respBody = JSON.stringify(respBody);
console.info(`About to return status: ${sCode}, respBody: ${respBody}`);
}
const response = {
statusCode: sCode,
body: respBody
};
return response;
};
template.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
movie-crud-app
Globals:
Function:
Timeout: 3
Resources:
GetItemsFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: lambda-handlers/get-items/
Handler: get-items.lambdaHandler
Runtime: nodejs18.x
Description: A simple function to get items
Policies:
#Give Create/Read/Update/Delete permissions to MovieTable
- DynamoDBCrudPolicy:
TableName: !Ref MovieTable
Environment:
Variables:
#Make table name accessible as environment variable from function code during execution
MOVIE_TABLE: !Ref MovieTable
Architectures:
- x86_64
Layers:
- !Ref DependenciesLayer
Events:
GetItems:
Type: Api
Properties:
Path: /items
Method: get
DependenciesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: sam-app-dependencies
Description: Dependencies for movie crud app (aws-sdk/client-dynamodb)
ContentUri: dependencies/
CompatibleRuntimes:
- nodejs18.x
LicenseInfo: 'MIT'
RetentionPolicy: Retain
MovieTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: year
AttributeType: N
- AttributeName: title
AttributeType: S
KeySchema:
- AttributeName: year
KeyType: HASH #Partition key
- AttributeName: title
KeyType: RANGE #Sort key
ProvisionedThroughput:
ReadCapacityUnits: 10
WriteCapacityUnits: 10
TableName: "MovieTable"
我100%确定API网关正在达到Lambda函数。来自AWS Cloudwatch的日志:
ERROR调用错误
{“错误类型”:“错误”,“错误消息”:“没有有效的终结点提供程序可用。",“堆栈”:[“错误:没有可用的有效终结点提供程序。",
“位于/var/运行时/节点模块/@aws-sdk/中间件-serde/dist-cjs/序列化中间件.js:10:15”,
“位于/var/运行时/节点模块/@aws-sdk/库-动态数据库/dist-cjs/基本命令/动态数据库文档客户端命令.js:11:20”,
“位于/opt/节点js/节点模块/@aws-sdk/中间件记录器/dist-cjs/记录器中间件.js:5:28”,
“位于/var/运行时/节点模块/@aws-sdk/lib-dynamodb/dist-cjs/命令/扫描命令.js:28:28”,
“位于动态数据库文档客户端.send(/var/运行时/节点模块/@aws-sdk/smithy客户端/dist-cjs/客户端.js:20:20)",
“在运行时。lambdaHandler [作为处理程序](文件:///var/任务/获取项. mjs:60:29)",
运行时。handleOnceNonStreaming(文件:///变量/运行时/索引. mjs:1085:29)
]
}
如果我使用curl,我会收到内部服务器错误。
此应用程序通过AWS sam部署:sam deploy --guided
我曾尝试用一个使用boto 3的简单python脚本向我的dynamoDB表发送扫描命令,这似乎起作用了,所以我想可能是权限或角色有问题,我可能错过了。
Roles assigned to my lambda function:
获取项函数角色策略的JSON:
{
"Statement": [
{
"Action": [
"dynamodb:GetItem",
"dynamodb:DeleteItem",
"dynamodb:PutItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem",
"dynamodb:BatchWriteItem",
"dynamodb:BatchGetItem",
"dynamodb:DescribeTable",
"dynamodb:ConditionCheckItem"
],
"Resource": [
"arn:aws:dynamodb:us-east-1:[mytablename]",
"arn:aws:dynamodb:us-east-1:[mytablename]/index/*"
],
"Effect": "Allow"
}
]
}
Perhaps the issue may have something to do with the integration request being LAMBDA_PROXY?
2023年3月6日更新:显然,任何发送到空数据表的Get或Scan命令都会自动给予“No valid endpoint provider”错误。一旦我用模拟数据填充了表,我就不再收到该错误。但是,如果我尝试使用Postman调用API,我仍然会收到403 Forbidden错误。如果我使用curl或Web浏览器,该函数可以工作。我的下一步是修复Postman的问题。
2条答案
按热度按时间a8jjtwal1#
假设模板正确地创建了资源,请尝试使用以下代码。
gtlvzcf82#
显然,任何发送到空数据表的Get或Scan命令都会自动给予“No valid endpoint provider”错误。一旦我用模拟数据填充了表,我就不再收到该错误。我能够通过创建一个API键并将其用于Postman来解决Postman问题。