Skip to main content

Working with AWS Lambda

This guide will walk you through integrating the API into an AWS Lambda function that you can call from any frontend application. In this case, we'll be using React.

Our goal is to pull a list of products from a project and render them to a webpage after calling an AWS Lambda function. If you don't have a project with Ecommerce data, you can use our Shape Shop starter project.

Let's jump in.

Follow Along

Follow along with this guide by checking out our starter project repo. Our starters let you instantly deploy a pre-configured project.

Setup

To connect to your project, you need your API Endpoint and an API key.

If you haven't created a project yet, follow this guide to do so.

If you already have a project, your API Endpoint will be in the admin UI. In the home tab, look for the "Useful Snippets" section.

Copy the API Endpoint and save it somewhere secure.

To get an API Key, you'll have to create one. Read our docs on creating an API Key here.

Creating your React app

You can use any frontend framework for this project, but for the sake of simplicity we'll use React.

Navigate to a folder where you'd like to store your project, and open up your terminal. Create a React app:

npx create-react-app lambda-example

Now open this new project directory in your favorite IDE, or navigate to it in your terminal.

You're all set. Time to configure your AWS Lambda Endpoint.

Configuring your AWS Lambda Endpoint

Your AWS Lambda Endpoint is the endpoint you can make a request to execute your lambda function. Think of it as an API endpoint that AWS sets up for you, with minimal code needed on your end.

Setting up your endpoint requires a few things to be established:

  1. You have an AWS account. Sign up for one here.

  2. You have an IAM user account with programmatic access to any endpoints you create. Read the guide to setting up an IAM user here.

Be sure to save your access key ID and secret access key when creating an IAM user.

With those initial steps out of the way, let's get started.

Setting up Serverless framework

Though you can configure your lambda endpoint with the AWS CLI, it's much simpler to use the Serverless CLI framework. Back in your local machine's terminal, run the following command to install it:

npm install -g serverless

Now it'll be much easier to manage and deploy changes to your AWS account.

Change directories into your frontend app in the terminal.

Now add your IAM user's credentials to serverless:

serverless config credentials --provider aws --key YOUR-KEY-HERE --secret YOUR-SECRET-HERE -o

Serverless makes it easy to set up an AWS lambda template once everything is configured. Use the following command to create a folder for your lambda template inside your project's root directory:

serverless create --template aws-nodejs --path aws-graphqlapi

Now you have a folder called aws-graphqlapi in the root directory of your project.

If you check its contents, you'll find a handler.js file, which is where your functions will live. By default, this handler.js module is exporting a method called hello. Rename it to getProductList. The file should now look like this:

handler.js
'use strict';

module.exports.getProductList = async (event) => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Go Serverless v1.0. Your function executed successfully.',
input: event,
},
null,
2
),
};

// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0. Your function executed successfully.', event };
};

You can test it out locally by changing directories into this folder and running the following command in your terminal:

serverless invoke local --function getProductList

The status code and body from the function above should print out in the console.

There's also a serverless.yml file which you can use to configure your serverless setup. Open that file and look for functions. You should find a section of the file that looks like this:

serverless.yml
functions:
hello:
handler: handler.hello

Go ahead and swap out the word hello for getProductList. Now that section of the file should look like this:

serverless.yml
functions:
getProductList:
handler: handler.getProductList

You must also add an event, which is a property you can add to a serverless.yml file to generate an API endpoint for a function you want to deploy. Add the following code to this section of the file, so that it looks like this:

serverless.yml
functions:
getProductList:
handler: handler.getProductList
events:
- http:
path: productlist
method: get

In the above code, we set the path to be productlist, but you're free to make the path whatever you want.

And one last thing: Environment variables.

You can't make a request to your project's API if you don't have the endpoint and key. After adding events to your yaml file, you need to add the environment property and set your variables as shown below:

serverless.yml
functions:
getProductList:
handler: handler.getProductList
events:
- http:
path: productlist
method: get
environment:
GRAPHQL_API_KEY: ${env:GRAPHQL_API_KEY}
GRAPHQL_ENDPOINT: ${env:GRAPHQL_ENDPOINT}

You'll then need to create a .env file in the aws-graphqlapi folder, which should look like this:

.env
GRAPHQL_API_KEY=Your-Key-Here

GRAPHQL_ENDPOINT=Your-Endpoint-Here

To learn where to get your project's API Endpoint and API Key, check out this section on connecting your project above.

We can easily deploy this function now, but first let's make sure we're fetching the data we need from AWS. Go back to aws-graphqlapi/handler.js.

You'll need to create a POST request to your API endpoint in the handler module, then forward that data in the body of the response your handler sends. Whatever frontend application calls the endpoint should always get that data.

To make this POST request, we have to do a few things. First, install Axios for your lambda function, which is a node library that simplifies http requests.

Change directories into the serverless service folder:

cd aws-graphqlapi

Then initialize npm so you can use node packages in your lambda function.

npm init -y

Now you're ready to install axios:

npm i axios

You'll then need to edit the .npmignore file in your aws-graphqlapi directory to remove node_modules and any instances of .env that appear there. The file should look like this:

.npmignore
# package directories
jspm_packages

# Serverless directories
.serverless

With that file configured properly, your npm packages will be uploaded along with your code, which means axios will be able to make requests.

Finally, it's time to write the function.

Here's how your handler.js file should look:

handler.js
const axios = require('axios');

module.exports.getProductList = async (event) => {
try{
const result = await axios.post(
process.env.GRAPHQL_ENDPOINT,
{
query: `query {
getProductList{
items{
price
name
_id
image{
sourceUrl
}
}
}
}
`
},
{
headers: {
'Authorization': `Bearer ${process.env.GRAPHQL_API_KEY}`
}
});

return {
statusCode: 200,
body: JSON.stringify({
products: result.data.data.getProductList.items
}),
};
} catch (err) {

return {
statusCode: 500,
body: JSON.stringify({
message: `Failed to fetch data from the GraphQL API. ${err}`
}),
};
}
};

The above handler module fetches a list of products from your project, then returns that list in an HTTP response if successful. If unsuccessful, it returns an error message and a 500 status code.

That's all you need for a simple fundamental setup.

Now all you have to do is deploy the function, which takes no time at all.

Change directories into the serverless service folder, which in this case is called aws-graphqlapi

cd aws-graphqlapi

Run the deploy command:

serverless deploy

The process for deploying your function to AWS may take some time, but when it's done you should see a list of data about your function in the console. It should list things like the service name, region, stack, api keys, and of course the endpoint you need to hit to execute the function.

Your endpoint will be listed under endpoints, where it says GET.

Copy the endpoint, and you're ready to fetch this data on the frontend.

Calling your AWS Lambda function from the frontend

Now for the easy part. You need to fetch your product list from your AWS endpoint and display it with React. You can check out our guide on working with React if you'd like an in-depth look at the process.

For this guide, we'll move somewhat quickly through an explanation of the code.

In your React app, change directories back to the root directory of your project:

cd ..

Now it's just a matter of fetching the data in your src/App.js component. Just remember that if you used the code above for your handler.js, your lambda function will return an array rather than an object.

Create a .env file and add your AWS endpoint to it like so:

.env
REACT_APP_AWS_ENDPOINT=Your-Endpoint-Here

And here's what your App.js might look like:

App.js
import { useState, useEffect } from 'react';

function App() {

const [productList, setProductList] = useState(null);

useEffect(() => {
(async ()=>{
try {
const result = await fetch(process.env.REACT_APP_AWS_ENDPOINT);
const resultJSON = await result.json();
setProductList(resultJSON.products);
console.log(resultJSON);
} catch (err){
console.log('Failed to get data from AWS lambda function', err);
}
})();
}, [])

return (
<main style={{width:'50%',margin:'auto', display:'flex', flexDirection:'column'}}>
{productList && productList.map(product=>(
<div key={product._id} style={{display:'flex', flexDirection:'column'}}>
<img alt={product.name} style={{maxWidth:'800px'}} src={product.image.sourceUrl}></img>
<h2>{product.name}</h2>
<b>{product.price}</b>
</div>
))}
</main>
);
}

export default App;

The above code fetches a product list from an AWS endpoint and displays it in a series of divs with React.

Run the project with:

npm run start

Here's what the page should look like:

Still need help? Get in touch with us.

Other ways to use AWS Lambda

Check out our guide on connecting AWS Lambda to your project as service.

You can also see our guide for using AWS Lambda as an API Resolver.