6

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.

iSkore
  • 7,394
  • 3
  • 34
  • 59
ARUNBALAN NV
  • 1,634
  • 4
  • 17
  • 39
  • Can you print the string right before it is going to be parsed? – johni Sep 02 '16 at 12:47
  • @johni is there any way to do this on api gateway integration request maping? – ARUNBALAN NV Sep 02 '16 at 12:53
  • There should be. I'm not an Api Gayeway expert, but from the material that I've studied the past couple of days, there seems to be support for that. Anyway, I think your problem has to do with the string that you're trying to parse. Nothing else, that does not have to do with AWS at all (IMO) – johni Sep 02 '16 at 12:55
  • That should answer your question regarding Api Gateway http://stackoverflow.com/q/31329958/3454745 – johni Sep 02 '16 at 13:40
  • Do we have to decode the string back in json template section of API Gateway? Or it solves this internally? – Kuldeep Yadav Oct 13 '18 at 05:00

4 Answers4

9

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("\\'","'")

Beau Herndon
  • 91
  • 1
  • 2
  • I'm trying this but I just get internal server error. ```"query": { #foreach($queryParam in $input.params().querystring.keySet()) "$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam)).replace(\"\\'\",\"'\")" #if($foreach.hasNext),#end #end } ``` – Joel Mar 06 '17 at 12:48
  • **NOTE**: If the mapping template is defined as part of a JavaScript/TypeScript string within a CDK app, you'll need to double up on the escape tokens, i.e. `$util.escapeJavaScript(data).replaceAll("\\\\'","'")` – Kris Dover Oct 25 '22 at 21:29
2

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.

Community
  • 1
  • 1
Lorenzo d
  • 2,016
  • 10
  • 17
0

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 );
...
iSkore
  • 7,394
  • 3
  • 34
  • 59
  • Actually i am sending parameter like this : invok_url?param=%5B%5B%229780786706211%22%2C%22Endurance%3A%20Shackleton%27s%20Incredible%20Voyage%22%2C%22Adventure%20Books%22%2C8.8%2C1%5D%5D – ARUNBALAN NV Sep 02 '16 at 11:56
0

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)

Ordiel
  • 2,442
  • 3
  • 36
  • 52