1

I have 2 Lambdas using Chalice behind an API Gateway. All endpoints are protected by a Cognito authorizer.

When I call GET /hello, I want the first Lambda to fetch data from the second Lambda:

# Lambda1
@app.route('/hello')
def say_hello():
    name = # fetch data from Lambda2
    return Response({'message': 'hello ' + name})

# Lambda2
@app.route('/name')
def a_name():
    return Response({'name': 'GLaDOS'})

This request doesn't have to go through the API Gateway + authorizer again, as it creates unnecessary overhead.

How to make this call directly?

cahen
  • 15,807
  • 13
  • 47
  • 78
  • I think the only way is to invoke it with the aws sdk. But if you need the response this means you can't invoke async and that means you pay twice. – roeland Jul 21 '20 at 14:12

1 Answers1

1

EDIT: I recommend the below solution only if you can't have an Internal API Gateway for any reason.


With the code below I could successfully invoke another Chalice Lambda directly (without going through the API Gateway + Authorizer again):

def invoke_sync(lambda_name: str,
                http_method: str,
                path: str,
                claims: dict,
                path_parameters: dict = None,
                http_request_body: str = None,
                query_string_parameters: dict = None,
                headers: dict = None):

    invoke_payload = {
        'path': path,
        'httpMethod': http_method,
        'headers': headers,
        'multiValueHeaders': {},
        'queryStringParameters': query_string_parameters,
        'multiValueQueryStringParameters': None,
        'pathParameters': path_parameters,
        'stageVariables': None,
        'requestContext': {
            'authorizer': {'claims': claims},
            'path': path,
            'resourcePath': path,
            'httpMethod': http_method,
        },
        'body': http_request_body,
    }

    lambda_response = boto3.client('lambda').invoke(FunctionName=lambda_name,
                                                    InvocationType='RequestResponse',
                                                    Payload=json.dumps(invoke_payload))

    payload = json.loads(lambda_response['Payload'].read())
    status_code = payload['statusCode']

    ...

Usage example:

invoke_sync(
    lambda_name='Users',
    claims=<claims-in-the-id-token>,
    http_method='GET',
    path='/users/{userId}',
    path_parameters={'userId': 123}
)

This call is synchronous. To create an asynchronous version of the above, use InvocationType='Event' as documented here.

Note that the payload used above would be exactly the same if using other languages or frameworks, given this is the format sent from the API Gateway to the Lambda functions.

cahen
  • 15,807
  • 13
  • 47
  • 78
  • what do you mean by claims=? Is this some value we can get from app.current_request? Any links to overall documentation to help understanding what claims are in the first place would also be really helpful – Edward Spencer Sep 29 '22 at 12:06