Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke Lambda function from Amplify-generated React App without using API Gateway

I used Amplify to generate a static website and the underlying React app. Initially I also generated an API endpoint but, because my lambda function may run over the API Gateway timeout limit (29 seconds), I need to invoke the lambda function directly from the generated React App, instead of going through API Gateway.

The code looks as follows, for the React page to authenticate using Cognito:

import Auth from '@aws-amplify/auth';
import { withAuthenticator } from 'aws-amplify-react';
import awsconfig from './aws-exports';

Auth.configure(awsconfig);

The above lines wrap the App (root) object and work as advertised. But since I do not want to use the API Gateway, how do I invoke the AWS Lambda function directly from React App?

The answers I could find talk about importing AWS etc, which seems to be in conflict with what we are trying to do here. I need to use the authenticated connection (which already works using the above code) when invoking lambda, so I cannot use generic invocation given in this example.

The Invoke API does not provide any examples as well.

Any advice is appreciated.

like image 326
LNI Avatar asked May 13 '19 06:05

LNI


1 Answers

Note: if you do not need a response after your long running lambda, then consider API Gateways' Asynchronous Invocation

Amplify calls this approach "working with service objects".

To do this you'll have to ensure that the role Cognito gives your authenticated users includes permissions for lambda:invoke as well as any additional permissions needed within the function. I'll assume you can do that for now, however you can see the Role-Based Access Control documentation, or ask another question if not.

To access these roles within Amplify you need to use the Auth.currentCredentials function, which returns a promise with a credentials object, which can then be used on an aws-sdk client.

For example:

import Auth from '@aws-amplify/auth';
import Lambda from 'aws-sdk/clients/lambda'; // npm install aws-sdk

Auth.currentCredentials()
  .then(credentials => {
    const lambda = new Lambda({
      credentials: Auth.essentialCredentials(credentials)
    });
    return lambda.invoke({
      FunctionName: 'my-function',
      Payload: JSON.stringify({ hello: world }),
    });
  })

You can see the full documentation for invoking lambdas on the AWS-SDK javascript documentation.

However you should be aware that the payload from API Gateway is constructed by AWS and includes much more information than just the body that the endpoint was called with, however when you invoke directly, all you'll get is the payload, so you'll have to build that payload object accordingly.

like image 56
thomasmichaelwallace Avatar answered Sep 25 '22 18:09

thomasmichaelwallace