Building a Serverless Not Hot Dog app

Ho Ming Li
Cloud Academy
Published in
6 min readAug 11, 2017

Inspired by the Not Hot Dog app by Jian Yang in the popular HBO show Silicon Valley, I set out to build my very own. I am not aware of its implementation, nor have I seen any references on how it can be built, so I’m on my own putting this together.

To build this serverless web application, I’ve come up with the following architecture. You’ll see that I won’t have a single server to manage. Awesome!

This application didn’t take long to build. After a couple of weekends, here is my application.

You can register if you choose to, the workflow is functional thanks to Amazon Cognito (more on this later). If you would rather not go through the sign-up, you can login with username jian-yang and password freerent.

This article is not intended to be a step-by-step guide. I’m documenting and sharing my journey building this application.

It all starts with a few lines of code

Just how difficult is it to get started with object detection and classification? Not difficult at all.

AWS launched many new services and features at re:Invent 2016. At the annual event, AWS introduced Amazon Rekognition, making it easy to add image analysis to your applications. Bingo! With less than 15 lines of code, I have a usable script that can identify whether or not an image is hot dog.

The above code passes the input argument (the supplied image file) to the is_hotdog function, then uses the rekognition client to detect labels for the image. When the label Hot Dog is found, the function returns True. The function returns False if Hot Dog is not found. Based on the function returning True or False, it prints out whether or not the image is a Hot Dog. Simple.

Building the Serverless Back End

Alright, now, with the basic prototype complete and working, I ported over the function to AWS Lambda. Instead of __main__, just define a handler function lambda_handler(event, context), and there you have a Lambda function. It required minimal code change. And, knowing that API Gateway supports binary files, I created an API with a PUT method to invoke my Lambda function. If you’re trying this yourself, don’t forget to enable CORS and to deploy your API before validating it.

I did have to make small code changes on the Lambda function to prepare for the image passed in from API Gateway in the source event. I need it to properly accept the image file from the front-end that I will be building. The most challenging part of the function is to handle multipart/form-data coming from the front end. I learned that the image data passed to the function included a few lines of metadata. I had to strip the metadata before passing it to Amazon Rekognition.

The resulting Lambda function:

Without the front end built, I used curl to verify the backend behavior when submitting multipart/form-data:

$ curl -XPUT https://<endpoint>/<stage>/<method> -F filename=”@image.jpg” -H “Content-Type:multipart/form-data”

Great! It’s working!

Static Website with Vue.js

With the backend working as desired, I then implemented a front end to this application that connects with the back end. I chose to host a static site on S3 as it is intuitive, easy, and cost effective. If you are not familiar with the set up, take a look at the documentation for setting up a bucket for Static Website Hosting.

There are many javascript frameworks to choose from and I have decided to use Vue.js as the project appears to be gaining in popularity and momentum. If you are implementing a similar application yourself, feel free to use the javascript framework you are most familiar with. I’m very new to Vue.js so I heavily borrowed code from How to Handle File Uploads in Vue 2 as a starting point. I modified the code and styled it differently. After some edits, with the code ready, I “built” the javascript locally and synced the files to S3, and the static site was live.

Getting the image to upload and also display was a little tricky. Thanks again to the article I referenced and the stackoverflow answer it linked, I was able to use readAsDataURL() to store the image data in sessionStorage, and then display the image by assigning the data from sessionStorage to the image src attribute.

Here’s a couple of screenshots showing a working Not Hot Dog web app!

The web app works identifying a Hot Dog! It’s also working indicating Pizza is Not Hot Dog!

Not so fast. I’m not done yet.

I could have stopped at this point with a working static site that can identify whether an image is Hot Dog. But I want to take it further. Thinking to myself, if I am realistically building a full application, there needs to be an authentication layer to my application. Amazon Cognito recently launched the public beta for built-in user interface (update: this feature is now generally available) to quickly add user sign up and sign in functionality. This new feature saved me a lot of work and time spent otherwise implementing an authentication layer.

To use this Cognito App Integration feature, first create a user pool by stepping through the wizard via the console, then configure app integration with a domain name, supply it with the sanctioned redirect_uri and off you go.

Not a line of code to have user registration using Cognito App Integration feature

Not quite. There is a catch. I faced a challenge with Cognito App Integration feature requiring HTTPS URI for redirects, but S3 static websites can only be served via HTTP. To solve this issue, I need an HTTPS endpoint to add to my App Integration configuration.

When an application needs to be served to users globally, an optimization technique is to cache content closer to the users. A content delivery network (CDN) typically has many points of presence across the globe for this purpose. I know my Not Hot Dog web application will definitely be serving tens of thousands of users globally (why wouldn’t it), I should be using a CDN, so in comes Amazon CloudFront. A CloudFront web distribution is fairly straightforward to set up. If you would like to read more about it, take a look at the documentation. CloudFront presents an HTTPS endpoint, and I will be using this HTTPS endpoint for my Cognito redirect. Problem solved.

All that is left to do is to add the record to my Route 53 hosted zone, and that is it. There you have my entirely serverless Not Hot Dog application. Hooray!

My colleagues suggested a fun easter egg for the application. Why not. I have built-in an easter egg. See if you can find out what it is.

AWS Services at a glance

Amazon API Gateway and AWS Lambda are the core services for a serverless back end. Simply define your REST interface with API Gateway, and configure it to invoke Lambda functions. API Gateway supports Swagger definitions. It can generate SDKs and documentations. Lambda is an event-driven compute platform. Lambda supports many different event sources, such as S3 Events, Cloudwatch Events, a voice command from an Amazon Echo, and many other triggers. Pairing API Gateway and Lambda together enables a scalable back end without worrying about servers. Landsat on AWS is powered by S3, API Gateway, and Lambda.

Amazon Cognito lets developers focus on creating excellent in-app experiences by taking care of the undifferentiated heavy lifting when it comes to user identity management. Cognito can also manage federated identities across social media identity providers, also supporting SAML. Check out this excellent blog post on securing API access with Cognito.

With Amazon Rekognition, applications can easily detect objects, scenes, and faces in images. Not only can it detect hot dogs, with a similar approach you can detect any image for any object. Others have used Rekognition to analyze emotions in faces, recognize celebrities, and even created a tool for public safety.

--

--

Ho Ming Li
Cloud Academy

@SpyCloud, ex Gremlins & AWS | Customer focused; Embrace change; Always do better | Inspired to change the world