Amazon web services 与SNS通信的AWS API网关

Amazon web services 与SNS通信的AWS API网关,amazon-web-services,amazon-sns,aws-api-gateway,Amazon Web Services,Amazon Sns,Aws Api Gateway,我正在构建一个将由Lambda函数提供服务的API,但我需要这些API是异步的,因此,我使用“AWS服务代理”发布SNS消息,然后让Lambda函数订阅相关SNS主题,以便接收请求的传递,而不是将API网关直接连接到Lambda函数。下面是一张说明流程的图片: 我已经单独测试了Lambda函数以及SNS和Lambda之间的发布/订阅消息传递,但是我正在努力使用SNS切换的API网关。文档非常简单,但我现在假设在POST请求中必须发送以下属性: 操作:API网关提供在UI中设置此操作,我已在发布

我正在构建一个将由Lambda函数提供服务的API,但我需要这些API是异步的,因此,我使用“AWS服务代理”发布SNS消息,然后让Lambda函数订阅相关SNS主题,以便接收请求的传递,而不是将API网关直接连接到Lambda函数。下面是一张说明流程的图片:

我已经单独测试了Lambda函数以及SNS和Lambda之间的发布/订阅消息传递,但是我正在努力使用SNS切换的API网关。文档非常简单,但我现在假设在POST请求中必须发送以下属性:

  • 操作:API网关提供在UI中设置此操作,我已在发布操作中添加了相应的SNS操作

  • 消息:POST消息的正文应该是JSON文档。它将由web客户端传递,并通过网关代理到SNS

  • TopicArn:表示我们要发布到的SNS主题。在我的设计中,这将是一个静态值/端点,因此我希望web客户机不必也传递它,但如果这样做更容易,也可以

  • 我尝试了很多东西,但都被卡住了。希望能在某个地方找到一个好的代码示例,但如有任何帮助,将不胜感激


    希望在我当前的尝试中添加更多的上下文:

    我曾尝试发布我的API,并使用Postman尝试获得有效的响应。以下是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网关中包含以下内容:


    通过将Lambda函数配置为AWS服务代理,可以使用API网关异步调用Lambda函数。配置基本上与您在中看到的相同,只是Lambda调用的uri更改为而不是/invoke/

    我只是猜测(我自己没有尝试过),但我认为您没有正确发送消息

    根据AWS在此的文档(),您需要以类似于
    应用程序/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格式的,但仍然需要像表单字段一样进行编码(一个笨拙的类比:)

    此外,根据commonparameters文档(),您还有一些额外的必填字段(通常的访问密钥、签名等)


    您尚未指定编写API网关所用的语言-可能有一个AWS SDK供您使用,而不是尝试手动编写REST请求)。

    我来自API网关团队

    我相信发布API的HTTP请求有几种格式,但我首先使用的是:

    AWS地区美国西部-2

    AWS服务sns

    AWS子域

    HTTP方法POST

    行动发布

    ==查询字符串==

    主题“foo”
    消息“bar”
    TopicArn'arn:aws:sns:us-west-2:XXXXXXXXXX:TestAPI'

    这对我发布消息起了作用

    如果你还有麻烦,请告诉我


    Jack

    在与AWS支持部门合作后,我最终实现了这一点。以下是我的解决方案:

    • 首先,即使您发送的是
      POST
      ,您也无法像预期的那样在消息体中发送JSON消息
    • 相反,您必须对JSON进行URL编码,并将其作为查询参数传递
    • 还请记住,您发送的JSON应该以根对象
      default
      开始,在SNS世界中,这意味着“默认通道”
    • 然后,Lambda最终会检测到SNS事件,您还必须提取出大量噪声才能获取JSON消息。为此,我创建了以下在Lambda函数中使用的函数:
    /**
    *当在AWS中运行时,它通过SNS运行
    *event wconfig.ich为事件数据添加了大量混乱,
    *这将测试SNS数据,并在必要时进行规范化
    */
    功能摘要SNS(e){
    如果(如记录){
    返回JSON.parse(decodeURIComponent(e.Records[0].Sns.Message)).default;
    }否则{
    返回e;
    }
    }
    /**
    *处理者
    *这是lambda函数的入口点
    */
    exports.handler=函数处理程序(事件、上下文){
    parent.event=abstractSNS(event);
    我想这样做:

    WebApp-->网关-->Lambda(使用Boto3在SNS中发布)--->SNS-->Lambda


    我认为,事情会更简单。

    如果有人仍在寻找原始问题的解决方案,仅通过API网关将JSON请求主体代理到SNS主题,这是可能的

    按照Ken上面描述的创建网关。然后简单地将主体代理到。您也可以在此处硬编码主题、主题等,或者使用

    例如:

    {
       //body
       "topic": "arn:aws:sns:1234567:topic"
    }
    
    可以映射到标题,如下所示:

    method.request.body.topic
    

    还请记住参数区分大小写;我还收到了OP的错误:
    “消息”:“无效参数:TopicArn或Targetran原因:所需参数没有值”

    唯一的问题是参数的大小写敏感性(具体来说应该是:“TopicArn”和“Message”)。这些参数在方法执行|后集成请求部分的“Name”字段中设置

    “Mapped from”的大小写很重要,因为它与通过方法请求配置发送的参数相匹配,但是发送到SNS的是“Integration Request”的“Name”字段,这就是我的错误所在

    这里是一个逐步的步骤