Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access HTTP request (headers, query string, cookies, body) object in lambda with http endpoint

I am trying to see how to access the request header and body values from with in the lambda code. If the request body is in JSON format, it automatically seems to be parsed and made available in the event object.

How can I access the complete query string, request body, request headers (cookies) for any type of incoming "Content-Type" request inside Lambda ?


The edits below are information I have gathered to help solve the question that may or may not be relevant. Please ignore them if you wish to.


EDIT:

I went through the existing questions on SE here and here. As per this thread, using $input.json('$') should do the trick. I guess the answers from these links above are already out-dated as API gateway by default seems to recognize JSON in the request and if so makes it available in the event object without any mapping templates being configured.

Setting the mapping as suggested does not work for me. It does not contain the request header information.

Here are screen shots on how it is configured.

enter image description here


enter image description here

The "headers" key returns a blank value. Using $input.params('$') or "$input.params('$')" errors out.


EDIT 2

Tried defining the headers in Method Request. Still not getting the User-Agent value inside lambda.

enter image description here


EDIT 3

I used the following template mapping at the API Gateway

{
    "request": $input.json('$'),
    "headers": "$input.params()"
}

and the below code in lambda

context.succeed("event.key32:"+JSON.stringify(event, null, 2) );

And the response generated by the API gateway shows this enter image description here

Looking at the "headers" value in the response, it looks like the AWS-SDK/API gateway/cloudfront strips off all headers received from the HTTP client ? Here is the full text from the JSON returned by the $input.params().header

header={CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, Content-Type=application/json, Via=1.1 5d53b9570d94ce920abbd471.cloudfront.net (CloudFront), 1.1 95eea7baa7ec95c9a41eca9e3ab7.cloudfront.net (CloudFront), X-Amz-Cf-Id=GBqmObLRy6Iem9bJbVPrrW1K3YoWRDyAaMpv-UkshfCsHAA==, X-Forwarded-For=172.35.96.199, 51.139.183.101, X-Forwarded-Port=443, X-Forwarded-Proto=https}}

It doesn't have the User-Agent string in the header, although as the screenshot shows above, it was sent by the REST client. Interestingly, the entire query string is made available. Not sure if this is an intended way to access it.

like image 276
user3526 Avatar asked Aug 06 '15 09:08

user3526


People also ask

How do you access headers in Lambda function?

To pass custom headers from an API Gateway API to a Lambda function, use a body mapping template. The API sends the updated API request to a Lambda function to process the headers. Then, the Lambda function returns one or more header values from the original API request.


2 Answers

Seems like if no "Content-Type" is sent, AWS API Gateway defaults it to "application/json": https://forums.aws.amazon.com/thread.jspa?threadID=215471

So just define the Mapping Template for "application/json".

like image 23
inakiabt Avatar answered Oct 10 '22 21:10

inakiabt


The request headers can be accessed using $input.params('header-name')

Surprisingly, the User-Agent header cannot be accessed with above code. You need to jump through the following hoop to retrieve it:

$context.identity.userAgent

The request body/payload should be accessible using the following code. More reference here, here and here:

{
   "reqbody": "$input.path('$')"
}

It is not yet clear if the request body is expected to be in JSON. It needs to be noted that the request is treated as UTF-8 according to this post.


There currently seems to be two bugs:

  1. The "User-Agent" header is missing/being stripped off by the Amazon API.
  2. When the header values contain a double quote ("), the lambda function is not executed. (I do not see a log entry in the cloudwatch logs for such requests). Instead, the http response body contains the following:

    {
       "Type": "User",
       "message": "Could not parse request body into json."
    }
    

An example request that fails in Amazon API enter image description here

I believe this would need to be corrected to be able to implement the ETag mechanism for caching.

References:

An Etag is expected to be enclosed within double quotes. The browser is expected to send this exact value back through the If-None-Match header, and this is where Amazon API breaks.

Syntax for ETag?

HTTP: max length of etag

http://gsnedders.com/http-entity-tags-confusion

like image 175
user3526 Avatar answered Oct 10 '22 23:10

user3526