I am building an API which will be serviced by Lambda functions but I need these to be asynchronous so rather than connecting the API-Gateway directly to the Lambda function
You could use API Gateway to invoke your Lambda function asynchronously by configuring it as an AWS service proxy. The configuration is basically the same you see in this GitHub sample, with the exception that the uri for the Lambda invocation changes to /invoke-async/ instead of just /invoke/
If anybody is still looking for a solution to the original problem, proxying a JSON request body to an SNS topic via API gateway alone, it's possible.
Create the gateway as Ken describes above. Then simply proxy the body to the Integration Request's query parameters. You can also hard code Subject, TopicArn, etc here, or map those from the request's body using a JsonPath.
For example:
{
//body
"topic": "arn:aws:sns:1234567:topic"
}
Could be mapped to a header as:
method.request.body.topic
I am just speculating (haven't tried this myself), but I think you are not sending the message correctly...
Based on AWS's documentation here (http://docs.aws.amazon.com/sns/latest/api/API_Publish.html), you need to POST the message in what seems to be the application/x-www-form-urlencoded
encoding like this:
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
That is, the message body looks the way a browser would encode form data. Your message can be JSON formatted, but still needs to be encoded as if it was a form field (an awkward analogy :)).
Also, based on the common parameters documentation (http://docs.aws.amazon.com/sns/latest/api/CommonParameters.html), you have a number of additional required fields (the usual access key, signature and so on).
You have not specified what language you are writing your API Gateway in - there might be an AWS SDK for it that you can use, instead of trying to manually compose the REST requests).
I'm from the Api Gateway team.
I believe there are a few formats for the HTTP request to the Publish API, but here's the one I used first:
AWS Region us-west-2
AWS Service sns
AWS Subdomain
HTTP method POST
Action Publish
== query strings ==
Subject 'foo'
Message 'bar'
TopicArn 'arn:aws:sns:us-west-2:xxxxxxxxxxxx:test-api'
This worked for me to publish a message.
Let me know if you have further troubles.
Jack
I would do it like:
WebApp --> Gateway --> Lambda ( Use Boto3 to publish in SNS ) --> SNS -->Lambda
I think, things will be simpler.
Also remember parameters are case sensitive; I also received the OP's error: "Message": "Invalid parameter: TopicArn or TargetArn Reason: no value for required parameter"
The only problem was case sensitivity of the parameters (specifically it should be: "TopicArn" and "Message"). These are set in the Method Execution | POST - Integration Request section, in the "Name" field.
The capitalization of the "Mapped from" is important that it matches the params being sent through from the Method Request configuration, but what is sent on to SNS is the "Name" field of "Integration Request", and that is what I had wrong.