We're creating a web application for a unicorn ride-sharing service called Wild Rydes The app will let you create an account and log in, then request a ride by clicking on a map (powered by ArcGIS). The code can also be extended to build out more functionality.
All services used are eligible for the AWS Free Tier. Outside of the Free Tier, there may be small charges associated with building the app (less than $1 USD), but charges will continue to incur if you leave the app running. Please see the end of the YouTube video for instructions on how to delete all resources used in the video.
The application code is here in this repository.
Here is the code for the Lambda function, originally taken from the AWS workshop, and updated for Node 20.x:
import { randomBytes } from 'crypto';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
const client = new DynamoDBClient({});
const ddb = DynamoDBDocumentClient.from(client);
const fleet = [
{ Name: 'Angel', Color: 'White', Gender: 'Female' },
{ Name: 'Gil', Color: 'White', Gender: 'Male' },
{ Name: 'Rocinante', Color: 'Yellow', Gender: 'Female' },
];
export const handler = async (event, context) => {
if (!event.requestContext.authorizer) {
return errorResponse('Authorization not configured', context.awsRequestId);
}
const rideId = toUrlString(randomBytes(16));
console.log('Received event (', rideId, '): ', event);
const username = event.requestContext.authorizer.claims['cognito:username'];
const requestBody = JSON.parse(event.body);
const pickupLocation = requestBody.PickupLocation;
const unicorn = findUnicorn(pickupLocation);
try {
await recordRide(rideId, username, unicorn);
return {
statusCode: 201,
body: JSON.stringify({
RideId: rideId,
Unicorn: unicorn,
Eta: '30 seconds',
Rider: username,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
} catch (err) {
console.error(err);
return errorResponse(err.message, context.awsRequestId);
}
};
function findUnicorn(pickupLocation) {
console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude);
return fleet[Math.floor(Math.random() * fleet.length)];
}
async function recordRide(rideId, username, unicorn) {
const params = {
TableName: 'Rides',
Item: {
RideId: rideId,
User: username,
Unicorn: unicorn,
RequestTime: new Date().toISOString(),
},
};
await ddb.send(new PutCommand(params));
}
function toUrlString(buffer) {
return buffer.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
function errorResponse(errorMessage, awsRequestId) {
return {
statusCode: 500,
body: JSON.stringify({
Error: errorMessage,
Reference: awsRequestId,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
}Here is the code used to test the Lambda function:
{
"path": "/ride",
"httpMethod": "POST",
"headers": {
"Accept": "*/*",
"Authorization": "eyJraWQiOiJLTzRVMWZs",
"content-type": "application/json; charset=UTF-8"
},
"queryStringParameters": null,
"pathParameters": null,
"requestContext": {
"authorizer": {
"claims": {
"cognito:username": "the_username"
}
}
},
"body": "{\"PickupLocation\":{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}"
}- User Authentication: Managed with AWS Cognito.
- Ride Matching: Randomly assigns a unicorn from a predefined fleet.
- Backend Logic: Implemented using AWS Lambda (Node.js).
- Data Persistence: Ride details stored in DynamoDB.
- Scalable Design: Built using AWS Free Tier services with minimal costs (<$1 USD for non-free usage).
- The backend assigns a unicorn to a user request based on the pickup location and logs ride details to the database.
- Includes robust error handling and adherence to CORS policies.
- Lambda function enables rapid, serverless deployment and is testable using JSON-based inputs.