我正在构建一个由Lambda函数提供服务的API,但我需要这些API是异步的,而不是将API-Gateway直接连接到Lambda函数我使用" AWS服务代理&# 34; 发布 SNS消息,然后让Lambda函数订阅相关的SNS主题,以便它接收请求的传递。这是一张说明流程的图片:
我已经单独测试了Lambda函数以及SNS和Lambda之间的pub / sub消息传递,但我正在努力使用API-Gateway进行SNS切换。文档非常简单但我现在假设的是必须在POST请求中发送以下属性:
操作:API-Gateway提供在UI中设置此功能,我已添加发布操作,这是相应的SNS操作
消息:POST消息的正文应该是JSON文档。它将由Web客户端传递,并通过网关代理到SNS。
TopicArn :表示我们要发布的SNS主题。在我的设计中,这将是一个静态值/端点,所以我更喜欢网络客户端也不必通过它,但如果更容易做到这一点也会没问题。
我尝试过很多东西,但我只是卡住了。很想在某处找到一个好的代码示例,但任何帮助都会受到赞赏。
希望在我目前的尝试中添加更多背景信息:
我尝试发布我的API并使用Postman尝试获得有效的响应。这是邮递员屏幕(一个用于标题变量,一个用于JSON正文):
这会导致以下错误消息:
{
"Error": {
"Code": "InvalidParameter",
"Message": "Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter",
"Type": "Sender"
},
"RequestId": "b33b7700-e8a3-58f7-8ebe-39e4e62b02d0"
}
该错误似乎表明 TopicArn 参数未发送到SNS,但我在API网关中包含以下内容:
答案 0 :(得分:8)
我来自Api Gateway团队。
我相信发布API的HTTP请求有几种格式,但这是我首先使用的格式:
AWS Region us-west-2
AWS Service sns
AWS子域
HTTP方法POST
行动发布
==查询字符串==
主题'foo'
消息'bar'
TopicArn'arn:aws:sns:us-west-2:xxxxxxxxxxxx:test-api'
这对我发布了一条消息。
如果您有进一步的麻烦,请告诉我。
杰克
答案 1 :(得分:6)
在使用AWS支持后,我最终确保了这一点。这是我的解决方案:
POST
,你也 能够像你期望的那样在邮件正文中发送JSON邮件default
的根对象开头,在SNS-world中表示“默认频道”
/**
* When this is run in AWS it is run "through" a SNS
* event wconfig.ich adds a lot of clutter to the event data,
* this tests for SNS data and normalizes when necessary
*/
function abstractSNS(e) {
if (e.Records) {
return JSON.parse(decodeURIComponent(e.Records[0].Sns.Message)).default;
} else {
return e;
}
}
/**
* HANDLER
* This is the entry point for the lambda function
*/
exports.handler = function handler(event, context) {
parent.event = abstractSNS(event);
答案 2 :(得分:1)
您可以使用API网关通过将其配置为AWS服务代理来异步调用Lambda函数。配置与this GitHub sample中的配置基本相同,但Lambda调用的uri更改为/invoke-async/而不是/ invoke /
答案 3 :(得分:1)
我只是猜测(我自己没试过),但我认为你没有正确发送信息......
根据此处的AWS文档(http://docs.aws.amazon.com/sns/latest/api/API_Publish.html),您需要以类似于application/x-www-form-urlencoded
编码的方式发布消息:
POST http://sns.us-west-2.amazonaws.com/ HTTP/1.1
...
Action=Publish
&Message=%7B%22default%22%3A%22This+is+the+default+Message%22%2C%22APNS_SANDBOX%22%3A%22%7B+%5C%22aps%5C%22+%3A+%7B+%5C%22alert%5C%22+%3A+%5C%22You+have+got+email.%5C%22%2C+%5C%22badge%5C%22+%3A+9%2C%5C%22sound%5C%22+%3A%5C%22default%5C%22%7D%7D%22%7D
&TargetArn=arn%3Aaws%3Asns%3Aus-west-2%3A803981987763%3Aendpoint%2FAPNS_SANDBOX%2Fpushapp%2F98e9ced9-f136-3893-9d60-776547eafebb
&SignatureMethod=HmacSHA256
&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE
&SignatureVersion=2
&Version=2010-03-31
&Signature=vmqc4XRupKAxsDAdN4j4Ayw5LQljXMps3kss4bkDfCk%3D
&Timestamp=2013-07-18T22%3A44%3A09.452Z
&MessageStructure=json
也就是说,消息体看起来像浏览器对表单数据进行编码的方式。您的消息可以是JSON格式的,但仍然需要编码,就好像它是一个表单字段(一个尴尬的类比:))。
此外,根据常用参数文档(http://docs.aws.amazon.com/sns/latest/api/CommonParameters.html),您还有许多其他必填字段(通常的访问密钥,签名等)。
您尚未指定编写API网关的语言 - 您可以使用AWS SDK,而不是尝试手动编写REST请求。)
答案 4 :(得分:1)
我会这样做:
WebApp - >网关 - > Lambda(使用Boto3在SNS中发布) - > SNS - > Lambda
我认为事情会更简单。
答案 5 :(得分:1)
还请记住,参数区分大小写;我还收到了OP的错误:"Message": "Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter"
唯一的问题是参数是否区分大小写(具体来说应该是:“ TopicArn”和“ Message”)。这些是在“方法执行” |“方法执行”中设置的。 POST-集成请求部分,在“名称”字段中。
“映射自”的大小写很重要,因为它与从“方法请求”配置中发送来的参数匹配,但是发送到SNS的是“集成请求”的“名称”字段,这就是我错了。
答案 6 :(得分:1)
这里有一个分步指南,供在浏览上述答案后仍然无法弄清楚的人使用。变量名称区分大小写,因此请确保准确无误。
打开发布方法
一种。选择方法请求
湾将请求验证器更改为 Validate body, query string parameters, and headers
C。展开 URL 查询字符串参数
d.添加以下两个查询字符串参数
名称:TopicArn
----> 选择必填
名称:Message
-----> 选择必填
返回 Post 方法并打开集成请求
一种。展开 URL 查询字符串参数
湾添加以下两个查询字符串参数
名称:TopicArn
映射自:method.request.querystring.TopicArn
名称:Message
映射自:method.request.querystring.Message
测试时,更改以下命令以匹配您的 SNS ARN 并将其放入查询字符串中。
TopicArn=arn:aws:sns:us-west-2:1234567890:SNSName&Message="Hello from API Gateway"
来源/更多信息:
API Gateway Proxy Integration Service Guide
SNS Publish Method Documentation
答案 7 :(得分:0)
如果有人仍在寻找解决原始问题的方法,仅通过API网关将JSON请求主体代理到SNS主题,就可以实现。
按照Ken上面的描述创建网关。然后只需将正文代理到Integration Request's query parameters。您还可以在此处硬编码Subject,TopicArn等,或使用JsonPath从请求的正文中映射它们。
例如:
{
//body
"topic": "arn:aws:sns:1234567:topic"
}
可以按以下方式映射到标头:
method.request.body.topic