Passing HTTP Post from AWS API GW to Lambda

2019-05-30 02:42发布

问题:

I process the HTTP POST from a service that does not support JSON (Mailgun). It appears if I create an AWS API GW for POST and pass this to an AWS Lambda function that the data must be in JSON. Other than trying to serialize the POST to JSON (which I would prefer not to), does anyone know if this is the case?

回答1:

I found a solution here, works for me.

https://forums.aws.amazon.com/thread.jspa?messageID=673012&tstart=0#673012

The following is from the original post for a complete answer.

Step-by-step instructions are as follows:

  1. Amazon API Gateway -> Click "Create API".
  2. API name = "myTestAPI", Clone from API = Do not clone from existing API, Description = "Test"
  3. Click "Create API".
  4. Click "Create Resource".
  5. Resource Name = "myTestInput", Resource Path = "mytestinput".
  6. Click "Create Resource".
  7. Click "Create Method".
  8. Select "POST" or "GET" as required and click the tick.
  9. Integration type = "Lambda function", pick region as appropriate, write code as appropriate to action / store form data.
  10. Click "Save", click "Ok" to grant permission.
  11. Click "Integration Request".
  12. Click "Mapping Templates".
  13. Click "Add mapping template".
  14. Content-Type is "application/x-www-form-urlencoded" and click the tick.
  15. Click "application/x-www-form-urlencoded".
  16. Click the pencil icon next to "Input passthrough".
  17. Select "Mapping template".
  18. Paste the following into the Template box:

--

## convert HTML POST data or HTTP GET query string to JSON

## get the raw post data from the AWS built-in variable and give it a nicer name
#if ($context.httpMethod == "POST")
 #set($rawAPIData = $input.path('$'))
#elseif ($context.httpMethod == "GET")
 #set($rawAPIData = $input.params().querystring)
 #set($rawAPIData = $rawAPIData.toString())
 #set($rawAPIDataLength = $rawAPIData.length() - 1)
 #set($rawAPIData = $rawAPIData.substring(1, $rawAPIDataLength))
 #set($rawAPIData = $rawAPIData.replace(", ", "&"))
#else
 #set($rawAPIData = "")
#end

## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length())

## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
 #set($rawPostData = $rawAPIData + "&")
#end

## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawAPIData.split("&"))

## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])

## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
 #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
 #if ($countEquals == 1)
  #set($kvTokenised = $kvPair.split("="))
  #if ($kvTokenised[0].length() > 0)
   ## we found a valid key value pair. add it to the list.
   #set($devNull = $tokenisedEquals.add($kvPair))
  #end
 #end
#end

## next we set up our loop inside the output structure "{" and "}"
{
#foreach( $kvPair in $tokenisedEquals )
  ## finally we output the JSON for this pair and append a comma if this isn't the last pair
  #set($kvTokenised = $kvPair.split("="))
 "$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$util.urlDecode($kvTokenised[1])"#{else}""#end#if( $foreach.hasNext ),#end
#end
}
  1. Click the tick next to the "Mapping template" dropdown.
  2. Click "<- Method Execution".
  3. Click "Deploy API".
  4. Deployment stage = "New stage", Stage name = "production".
  5. Click "Deploy".