ARUNBALAN NV
ARUNBALAN NV

Reputation: 1662

AWS Lambda Error : 'Could not parse request body into json ' when url parameter contains JSON array

I am trying to invoke my Lambda function by passing parameters as below. it contains apostrophe(').

https://invoke_url?param=[["kurlo jack's book","Adventure Books",8.8,1]]

Stringifyed to be 'https://invoke_url?param=%5B%5B%229780786706211%22s....`

I used the mapping below to pass parameter to lambda

  "query": {
    #foreach($queryParam in $input.params().querystring.keySet())
    "$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end

    #end
  }  

I got following error

{"message": "Could not parse request body into json: Unrecognized character escape \'\'\' (code 39)\n at [Source: [B@5b70c341; line: 29, column: 65]"}  

i have also tried after removing double quotes from mapping template. But did't work.

Upvotes: 6

Views: 17541

Answers (4)

Beau Herndon
Beau Herndon

Reputation: 111

Be sure to add .replaceAll("\\'","'") to your request body passthrough template after .escapeJavaScript(data)

I found this bit from AWS's documentation to be very helpful for this issue:

$util.escapeJavaScript()

Escapes the characters in a string using JavaScript string rules.

Note This function will turn any regular single quotes (') into escaped ones (\'). However, the escaped single quotes are not valid in JSON. Thus, when the output from this function is used in a JSON property, you must turn any escaped single quotes (\') back to regular single quotes ('). This is shown in the following example: $util.escapeJavaScript(data).replaceAll("\\'","'")

Upvotes: 11

iSkore
iSkore

Reputation: 7553

The "query string" (the part in the hyperlink after ?) must be a string. Whatever you have constructing that must be appended to it like: https://invoke_url?a=x&b=y

In your Lambda code put:

if( event.hasOwnProperty( 'params' ) )
    if( event.params.hasOwnProperty( 'querystring' ) )
        params = event.params.querystring;

(obviously some extraneous checks, probably unnecessary but ehh)

In your API Gateway go to:

APIs -> api_name -> Resources -> invoke_url -> GET -> Method Execution

Under URL Query String Parameters "Add query string" a and b (or whatever)

When you hit www.com/invoke_url?a=x&b=y you can now access them with:

...
params = event.params.querystring;
console.log( params.a, params.b );
...

Upvotes: 0

Ordiel
Ordiel

Reputation: 2633

Try changing your encoding of ' to %27 as per what is is defined in this W3Schools page (ironically their example does not encodes the single quote either, I guess its because it belongs to the "supported" ASSCII set of characters)

Upvotes: 0

Lorenzo d
Lorenzo d

Reputation: 2066

I don't have a solution but I have narrowed the root cause. Lambda does not seem to like single quotes to be escaped with a single slash.

If you hardcode your mapping template to look like this:

{
    "query-fixed": {
        "param": "[[\"kurlo jack\\'s book\",\"Adventure Books\",8.8,1]]"
    }
}

my test Lambda invocation succeeds. However, if you hardcode the template to this:

{
    "query-fixed": {
        "param": "[[\"kurlo jack\'s book\",\"Adventure Books\",8.8,1]]"
    }
}

I get the same error message that you got above. Unfortunately, the second variation is what API Gateway produces for the Lambda invocation.

A workaround might involve using the template to replace single quotes escaped with slash to two slashes. See Replace a Substring of a String in Velocity Template Language

I'll follow up with Lambda internally and update if I hear anything or have a functional workaround.

Upvotes: 2

Related Questions