Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get headers for a POST request from aws lambda event object (in python) where the incoming request has empty body but info in headers

This is with respect to google drive API integration where I have a Lambda python event code that gets triggered when I do . This is the push notification implentation of Google drive API.

In order to allow google drive push notification to call us, I have created the associated api gateway endpoint as webhook using their API. Now this lambda do gets triggered when I edit the file so this means that webhook is successful and google calls back the hook.

Google Drive sends HTTP POST messages to the webhook url once you do any change.
The following HTTP headers are returned with empty body to the lambda function:

{
        "Content-Type": "application/json; utf-8",
        "Content-Length": "5000",
        "X-Goog_Channel-ID": "05a349fd-c363-4d8c-9409-8b6f310b7379",
        "X-Goog-Channel-Token": "to66728b-21c7-4605-8445-d7a297b9ae7f",
        "X-Goog-Channel-Expiration": "Fri, 14 Oct 2016 20:05:58 GMT",
        "X-Goog-Resource-ID":  "SuIweVX_iBzKmM5PQVMbIDYFrr8",
        "X-Goog-Resource-URI": "https://www.googleapis.com/drive/v3/files/1QvVo67IJ3_o5g2tCyxpNA29JHx183-bOOblKMoSAGv4?acknowledgeAbuse=false&alt=json",
        "X-Goog-Resource-State":  "update",
        "X-Goog-Changed": "content,properties",
        "X-Goog-Message-Number": "480896"
}

However, the event object of lambda handler is empty. I assume that event object is the HTTP body and in my case the body is empty, so I have added custom mapping template in Integration Request (to retrieve headers) of the API Gateway POST method as the following:

#set($inputRoot = $input.path('$'))
{
  "Content-Type" : "$input.params('Content-Type')",
  "Content-Length" : "$input.params('Content-Length')",
  "X-Goog-Channel-ID" : "$input.params('X-Goog-Channel-ID')",
  "X-Goog-Channel-Token" : "$input.params('X-Goog-Channel-Token')",
  "X-Goog-Channel-Expiration" : "$input.params('X-Goog-Channel-Expiration')",
  "X-Goog-Resource-ID" : "$input.params('X-Goog-Resource-ID')",
  "X-Goog-Resource-URI" : "$input.params('X-Goog-Resource-URI')",
  "X-Goog-Resource-State" : "$input.params('X-Goog-Resource-State')",

      "X-Goog-Changed" : "$input.params('X-Goog-Changed')",
      "X-Goog-Message-Number" : "$input.params('X-Goog-Message-Number')",
      "body" : $input.json('$')
    }  

But I am not sure how should I retrieve these headers from event object if at all they are getting received from google drive. Just logging the event object shows it as empty {}. What is the expected mapping if the above is incorrect? Also, event['header-name'] is not even getting executed it seems as when I print print 'Event header:{}'.format(event['header-name']) I don't even get Event header statement in the logs. So it means the line is not exceuted but the line above that is executed which is simple print statement like print 'Printing results' I am not sure why the code is not getting there or if there is an error.

Could you please guide me how we can retrieve headers using event object in python? And if all my steps above look correct or am I missing something?

like image 577
Atihska Avatar asked Oct 26 '16 22:10

Atihska


People also ask

How do you get 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.


1 Answers

I was able to get this working without any problem. I can't tell from your post why your event object is empty. My best guess is that you forgot to add the headers to the "HTTP Request Headers" section of the Method Request.

Here's my Lambda function:

from __future__ import print_function

import json

print('Loading function')

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))

    print("Content-Type = " + event['Content-Type'])
    print("Content-Length = " + event['Content-Length'])
    print("X-Goog-Channel-ID = " + event['X-Goog-Channel-ID'])
    print("X-Goog-Channel-Token = " + event['X-Goog-Channel-Token'])
    print("X-Goog-Channel-Expiration = " + event['X-Goog-Channel-Expiration'])
    print("X-Goog-Resource-ID = " + event['X-Goog-Resource-ID'])
    print("X-Goog-Resource-URI = " + event['X-Goog-Resource-URI'])
    print("X-Goog-Resource-State = " + event['X-Goog-Resource-State'])
    print("X-Goog-Changed = " + event['X-Goog-Changed'])
    print("X-Goog-Message-Number = " + event['X-Goog-Message-Number'])
    print("body = " + event['body'])

    return {
        'statusCode': '200',
        'body': event['body'],
        'headers': {
            'Content-Type': 'application/json',
            'X-Goog-Channel-ID': event['X-Goog-Channel-ID'],
            'X-Goog-Channel-Token': event['X-Goog-Channel-Token'],
            'X-Goog-Channel-Expiration': event['X-Goog-Channel-Expiration'],
            'X-Goog-Resource-ID': event['X-Goog-Resource-ID'],
            'X-Goog-Resource-URI': event['X-Goog-Resource-URI'],
            'X-Goog-Resource-State': event['X-Goog-Resource-State'],
            'X-Goog-Changed': event['X-Goog-Changed'],
            'X-Goog-Message-Number': event['X-Goog-Message-Number'],
        }
    }

My mapping template is the same as yours.

Here's the return value from a test call, using the same input headers from your example:

{
  "body": "Test input body content",
  "headers": {
    "X-Goog-Resource-ID": "SuIweVX_iBzKmM5PQVMbIDYFrr8",
    "X-Goog-Channel-ID": "",
    "X-Goog-Resource-State": "update",
    "X-Goog-Changed": "content,properties",
    "X-Goog-Resource-URI": "https://www.googleapis.com/drive/v3/files/1QvVo67IJ3_o5g2tCyxpNA29JHx183-bOOblKMoSAGv4?acknowledgeAbuse=false&alt=json",
    "X-Goog-Message-Number": "480896",
    "X-Goog-Channel-Token": "to66728b-21c7-4605-8445-d7a297b9ae7f",
    "Content-Type": "application/json",
    "X-Goog-Channel-Expiration": "Fri, 14 Oct 2016 20:05:58 GMT"
  },
  "statusCode": "200"
}
like image 172
MikeD at AWS Avatar answered Oct 18 '22 00:10

MikeD at AWS