调用Dynamodb时PUT请求正常但GET请求失败的问题排查
问题描述
- PUT请求可正常执行,但所有GET请求均失败:
- 指定路径参数调用
GET /items/{id}时,返回错误:"An error occurred (ValidationException) when calling the GetItem operation: The provided key element does not match the schema"
- 使用
curl <link>调用GET /items获取全量数据时,返回:{"message":"Internal Server Error"}
- 指定路径参数调用
完整代码
import json import boto3 from botocore.exceptions import ClientError dynamodb = boto3.resource('dynamodb') table_name = 'my-table' table = dynamodb.Table(table_name) key = { 'id': { 'S': '1' } } def handler(event, context): body = None status_code = 200 headers = { 'Content-Type': 'application/json', } try: # Based on API Gateway Payload v2.0 if event['routeKey'] == 'PUT /items': request_json = json.loads(event['body']) put = table.put_item( Item=request_json ) body = f"Put item with id: {request_json['id']}" # Get all items elif event['routeKey'] == 'GET /items': scan = table.scan() items = scan.get('Items', []) body = items # Get an item based on the path parameter elif event['routeKey'] == 'GET /items/{id}': path_parameters = event['pathParameters'] id_value = path_parameters['id'] get = table.get_item( Key={ 'id': { 'S': id_value } } ) body = get.get('Item', None) # Delete an item based on the path parameter elif event['routeKey'] == 'DELETE /items/{id}': id_value = path_parameters['id'] delete = table.delete_item( Key={ 'id': id_value } ) body = f"Deleted item with id: {id_value}" else: raise Exception(f"Unsupported route: {event['routeKey']}") except ClientError as e: status_code = 400 body = str(e) finally: body = json.dumps(body) return { 'statusCode': status_code, 'body': body, 'headers': headers, }
问题分析与修复
核心问题1:GetItem的Key格式错误
使用boto3的resource模式操作DynamoDB时,无需手动指定数据类型标记(如{'S': id_value}),resource层会自动处理类型映射。你在PUT请求中直接传入request_json成功,说明表的id字段是字符串类型,因此GET请求的Key只需传{'id': id_value}即可,多余的类型标记会导致Schema不匹配的ValidationException。
核心问题2:DELETE路由变量未定义
DELETE分支中直接使用了path_parameters变量,但该变量仅在GET /items/{id}分支中定义,会触发NameError,且原代码未捕获非ClientError的异常,导致未处理的错误返回500状态码。
修复后的代码
import json import boto3 from botocore.exceptions import ClientError dynamodb = boto3.resource('dynamodb') table_name = 'my-table' table = dynamodb.Table(table_name) def handler(event, context): body = None status_code = 200 headers = { 'Content-Type': 'application/json', } try: if event['routeKey'] == 'PUT /items': request_json = json.loads(event['body']) table.put_item(Item=request_json) body = f"Put item with id: {request_json['id']}" elif event['routeKey'] == 'GET /items': scan_response = table.scan() body = scan_response.get('Items', []) elif event['routeKey'] == 'GET /items/{id}': path_parameters = event['pathParameters'] id_value = path_parameters['id'] get_response = table.get_item(Key={'id': id_value}) body = get_response.get('Item', None) elif event['routeKey'] == 'DELETE /items/{id}': path_parameters = event['pathParameters'] id_value = path_parameters['id'] table.delete_item(Key={'id': id_value}) body = f"Deleted item with id: {id_value}" else: raise Exception(f"Unsupported route: {event['routeKey']}") except ClientError as e: status_code = 400 body = str(e) except Exception as e: status_code = 500 body = str(e) finally: body = json.dumps(body) return { 'statusCode': status_code, 'body': body, 'headers': headers, }
修复要点说明
- 移除
GET /items/{id}中Key的类型标记,改为符合resource模式的简洁写法。 - 在
DELETE /items/{id}分支中新增path_parameters = event['pathParameters'],避免变量未定义错误。 - 新增普通Exception捕获,处理所有非ClientError的异常(如变量未定义、路由错误),返回500状态码并输出错误信息,便于排查。
- 优化变量命名(如
scan改为scan_response),提升代码可读性。
内容的提问来源于stack exchange,提问作者charles uneze
相关产品推荐
相关产品推荐

