从Python向AWS Gateway API提交数据至DynamoDB时遇验证异常
我一眼就揪出问题所在了——你的Python请求发送格式不对,导致API Gateway解析不到你传的JSON字段,进而触发了DynamoDB的空值验证错误。
核心原因
你在requests.post里用了data=payload参数,但payload是一个Python字典。当你用data传字典时,requests会自动把它编码成application/x-www-form-urlencoded格式的表单数据(类似ping=1.967&download=570.01这种),而不是你期望的JSON格式。虽然你手动设置了Content-Type: application/json,但实际发送的内容格式和头信息不匹配,API Gateway无法正确解析出JSON里的ping、download等字段,导致$input.path('$.ping')这类表达式取到的是空字符串,最终触发DynamoDB的ValidationException。
而你在AWS控制台测试时,是直接发送的纯JSON请求体,所以API Gateway能正常解析字段,数据也就顺利写入了DynamoDB。
修复方案
有两种简单的修复方式,选其中一种就行:
方案1:使用json参数代替data
requests库提供了json参数,直接传入字典的话,它会自动帮你把字典序列化为JSON字符串,并且正确设置请求头(即使你手动设置了Content-Type也没问题):
import requests payload = { 'ping': '1.967', 'download': '570.01', 'upload': '697.85', 'timestamp': '1527845073' } headers = {'content-type':'application/json'} r = requests.post("https:xxx.execute-api.us-east-1.amazonaws.com/beta/device", json=payload, headers=headers) print(r.status_code, r.reason) print(r.text)
方案2:手动将字典转为JSON字符串后传入data
如果你更习惯用data参数,可以先用json.dumps()把字典转成JSON字符串,再传进去:
import requests import json payload = { 'ping': '1.967', 'download': '570.01', 'upload': '697.85', 'timestamp': '1527845073' } headers = {'content-type':'application/json'} r = requests.post("https:xxx.execute-api.us-east-1.amazonaws.com/beta/device", data=json.dumps(payload), headers=headers) print(r.status_code, r.reason) print(r.text)
验证
修改后再发送请求,API Gateway就能正确解析你的JSON payload,Body Mapping Template也能正常取出各个字段,数据应该就能顺利写入DynamoDB了。
内容的提问来源于stack exchange,提问作者Gene Ellis

