Enabling HTTP Streaming with AWS Amplify and Lambda Function URLs

Introduction

AWS Amplify combined with Lambda function URLs introduces a powerful mechanism for building cloud-backed apps that can leverage HTTP streaming capabilities. This not only bypasses the need for the traditional API Gateway but also brings in the efficiency of streaming data directly to clients. In this guide, we’ll delve into setting this up with a React project.

Setting Up AWS Amplify React Project

  1. Creating the Project:
    Start by initializing a new AWS Amplify React project named “Example”:
    amplify init Example
  2. Adding Authentication:
    Incorporate authentication to your project using the auth category.
    amplify add auth
    Follow the prompts to set up the desired authentication method.
  3. Adding a Lambda Function:
    Add a function named “sampleFunction” to your project:
    amplify add function
    Walk through the prompts and name it “sampleFunction”.

Configuring the Lambda Function’s URL for HTTP Streaming

  • Editing the CloudFormation Template:
    Navigate to ./amplify/function/sampleFunction/sampleFunction-cloudformation-template.json and insert the following:

    "LambdaURL": { "Type": "AWS::Lambda::Url", "Properties": { "AuthType": "NONE", "InvokeMode": "RESPONSE_STREAM", "Cors": { "AllowCredentials": true, "AllowOrigins": [""], "AllowMethods": [""], "AllowHeaders": ["Content-Type", "Authorization"] }, "TargetFunctionArn": { "Fn::GetAtt": ["LambdaFunction", "Arn"] } } }

    Under output, add:
    "Url": { "Value": { "Fn::GetAtt": [ "LambdaURL", "FunctionUrl" ] } }
  • Exporting the Function URL to React:
    Construct a setenv.js file in your Amplify app’s root with the provided content. Then, adjust package.json with

    "scripts": { "setenv": "node setenv.js", "start": "npm run setenv && react-scripts start", "build": "npm run setenv && react-scripts build", "eject": "react-scripts eject" }

    Then create a setenv.js file in the root of your Amplify app with the following content:

    const fs = require('fs'); const amplifyMeta = JSON.parse(fs.readFileSync('./amplify/backend/amplify-meta.json', 'utf8')); const lambdaUrl = amplifyMeta.function.sampleFunction.output.Url; // Create a .env file with the URL fs.writeFileSync('./.env', REACT_APP_LAMBDA_URL=${lambdaUrl}\n);

    Modify package.json to include:

    "scripts": { "setenv": "node setenv.js", "start": "npm run setenv && react-scripts start", "build": "npm run setenv && react-scripts build", "eject": "react-scripts eject" }

    For local development, manually update the .env file:

    REACT_APP_LAMBDA_URL=[the url of the function]

Authenticated Calls from the UI

Integrate the following JWT and JWKS code snippets into your Lambda function to validate tokens from AWS Cognito:

exports.handler = awslambda.streamifyResponse(
async (event, responseStream, context) => {
try {
const token = event.headers.authorization;
if (!token) {
responseStream.write('Unauthorized');
responseStream.end();
return;
}
const decodedToken = await isTokenValid(token);
// Continue processing after verifying the token…} catch (error) {
  console.log('Error', error)
  responseStream.write('Unauthorized');
  responseStream.end();
  return;
}
// The rest of the logic...
}
)

Conclusion

By integrating AWS Amplify with Lambda function URLs, developers can streamline their cloud-based app development. This guide provides a clear path to set up, ensuring a robust and secure configuration.

Farid Fadaie

Hey there, my name is Farid Fadaie and I have been living in San Francisco Bay Area since 2011. Over the years, I've worn a few different hats—started off as an engineer, tried my hand at creating a couple of companies (lucky enough to see them get acquired), and eventually ventured into the world of products as a VP and even Chief Product Officer. Through it all, I’ve been on both sides of the table, managing engineering teams and diving deep into product stuff. This little space is where I share some of the things I've picked up along the way. If you find any of it helpful or just want to chat, I'm all ears. Thanks for dropping by!

Leave a Reply