FYI: this post talks briefly about tracking food intake. Some folks have a complex relationship with that! Also I wrote it nearly a year ago, but I never published it until now. Enjoy.

In the past I was a bitesnap user. It was an okay(?) enough app to capture what I eat without focusing too much on the nutritional facts label. But getting the data out of the app has two options: JSON or CSV. Ultimately I’d like to be able to build a nice-ish styled report from the app, but it seems like the folks who build it are busy working on their main product.

“I can probably get a layout that works well enough for ‘print to PDF’ with some javascript and a single HTML file” was my first thought. But then I realized that I am a child when it comes to the front-end JS ecosystem. It’s not that I couldn’t figure it out, but it was going to take a bit longer to make that magic happen. So I did what people do when they need a drill but instead have a wacky-waving inflatable arm-flailing tube thing: I wrote a lambda function in golang, deployed it using lambda + api gateway and lived to tell the tale.

This didn’t actually seem like it would have been that challenging, except between outputting a HTML template that worked well enough and then figuring out how to get it to play nice with an HTTP API Gateway was a bit of a challenge!

What Challenge?

My app worked OK when I ran fmt.Printf on a template - but when that HTML was returned through the Lambda handler I saw a bunch of unicode codepoints (think \u003c and \u003e everywhere). Turns out the API Gateway Proxy event types give more flexibility on what my function would return. At one point I got my HTML out of the app, but none of the other bits. Progress!

OK, so… output. I had been testing my API with curl -d@bitesnap-data.json and not curl -F 'data=@bitesnap-data.json – which, the latter would have better emulated a web form. This lead me down a quite the journey of multipart mime/form processing in Go. An extremely helpful block of code from Adam Drake’s Serverless with Lambda, API Gateway, and Go saved me a ton of time. Recreating the incoming request parameters inside of an http.Request{} struct made it easier to use the built-in Golang functions for parsing multipart forms.

Lastly: S3 still doesn’t do HTTPS on the edge! I tried to proxy the S3 bucket with the static pages in it but it’d only work if I didnt verify TLS end-to-end. That might be OK-enough for this use case, except the only way the API gateway would work with a fancy hostname and proxying is if I did verify TLS. So, I got forced into setting up some Cloudfront.

Anyways, it works now.

Is… Is it safe?

Probably? Like, the lambda only has a max execution time of 1 sec, and 128mb of RAM, an extremely low rate limit. Folks are welcome to set up their own rube goldberg machines since you can view the source on GitHub.