Wildcard domain serverless applications

Adding Licenses to Code Projects

I’ve been starting to get back into personal programming projects, especially as I get more familiar with Python and NodeJS. Hoping that some of the stuff I create is actually useful, I wanted to make sure it was appropriately licensed. GitHub makes it easy to attach a license when creating a new repository, but sometimes (a) I forget to set a license when starting, (b) maybe I’m not immediately sure what license to pick or (c) decide to change the license later.

None of these problems are particularly difficult to manage, but I wanted an easier solution. I stumbled across https://mit-license.org, which is a cool little PHP/Heroku project that hosts online versions of the MIT license. Fork the repo, add your user JSON doc, submit a pull request, and you’ve got a web license you can just provide a URL for in your LICENSE file. Pretty cool.

But the repo maintainer states it’s $7 per month for hosting. In the age of serverless, that’s insanity. Especially considering how infrequent requests to that site ought to be. So I thought, “why can’t this be serverless, and reduce that cost?”

So I rewrote the whole thing in Python, created a Lambda function, and hosted it with CloudFront and API Gateway.


The whole thing is backed by a DynamoDB table, which is a bit nicer since you can’t scrape email addresses off the JSON files anymore. I also added some options to allow for other licenses to be specified (as of this writing, I’ve added MIT and Apache-2.0, but more will soon follow).

User-based wildcard CNAMEs

One of the hardest problems I had to solve was mimicking the user-subdomain concept. After getting the code all written up and setting up my API Gateway, I discovered that while you can set a custom CNAME for an API Gateway, it doesn’t support wildcard CNAMEs. I’m not entirely sure why, but I’ve got to believe someone has reasons. (Maybe the API Gateway team hasn’t caught up to wildcard/SNI support which CloudFront added a few years ago?)

After a day and a half of brainstorming, I came up with a solution. Using CloudFront, I was able to write a very small and straight-forward Lambda@Edge function that rewrites a request URI. So if you type “https://angrychimp.code-license.org” into your address bar, CloudFront rewrites that to “https://{api-gateway-domain}/u/angrychimp”. Other URI parts are preserved so that we can provide the correct content. Then I cache the response for a week, since it should be largely static.

This isn’t an ideal implementation, since I’m still running the Lambda@Edge function on each request (maybe I’ll go back and see if I can adjust it to an Origin Request function, rather than a Viewer Request function, which will allow me to improve caching and reduce my function invocation frequency), but for now this is way better.

End result?

In the end, whether or not this translates to actual cost savings depends largely on request frequency. I had asked the other package maintainer what the monthly request volume looked like, but didn’t wait for a response before starting my project.

My next steps are to implement a process to request new user records (though I need to make sure I allow for a simple approval process, and avoid spam/bot requests), and figure out a way to allow people to update their existing registrations. Once done, I’ll throw this out on Reddit and see what happens. I think I can handle 10-50K requests monthly and still keep things under $7, since a lot of this should happen under the AWS free tier. We’ll see how it goes.

Then I need to figure out how to implement CI/CD on the code. It’ll be hard with the CloudFront piece, but AWS SAM provides some cool automated testing tools, and I’ve been looking for a fun project to use for learning how SAM works.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s