Skip to content

Instantly share code, notes, and snippets.

@pletcher
Last active September 10, 2015 20:03
Show Gist options
  • Save pletcher/f13951621c79634df864 to your computer and use it in GitHub Desktop.
Save pletcher/f13951621c79634df864 to your computer and use it in GitHub Desktop.
AWS Mapping for consume application/x-www-form-urlencoded and producing application/json (for, e.g., subsequent consumption by an AWS Lambda function)
## Original: https://forums.aws.amazon.com/thread.jspa?messageID=674293
## A lot of people have probably used the original and had it work well
## for them. However, I'm posting this gist to correct a subtle but
## frustrating bug in the original. Jump to the bottom for a comparison.
## convert HTML FORM POST data to JSON for insertion directly into a Lambda function
## get the raw post data from the AWS built-in variable and give it a nicer name
#set($rawPostData = $input.path('$'))
## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawPostData.length() - $rawPostData.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 = $rawPostData + "&")
#end
## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawPostData.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
## In the original function posted on the AWS Developer Forums, we always attempt
## to access `$kvTokenised[1]`. This throws a `java.lang.ArrayIndexOutOfBoundsException`
## in the case where our `$kvPair` looks like `key=`. `$kvPair.split("=")` in that case
## returns `["key"]` -- there is no index 1. So here we catch this error by initializing
## `$kvValue` as an empty string and assigning it to `$kvTokenised[1]` only if
## `$kvTokenised.size() == 2`. (Velocity seems to override normal Java
## Array behavior -- we can't just use `$kvTokenised.length`.)
#set($kvTokenised = $kvPair.split("="))
#set($kvKey = $kvTokenised[0])
#set($kvValue = "")
#if ($kvTokenised.size() == 2)
#set($kvValue = $kvTokenised[1])
#end
"$util.urlDecode($kvKey)" : "$util.urlDecode($kvValue)"#if( $foreach.hasNext ),#end
#end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment