I spent a year learning Rust to avoid a 5 minute PHP job

or, Why I ended up writing a Rust application to process my form submissions

Posted by Orville Bennett on 3 March 2022
Read time: about 6 minutes

Welcome, dear traveller. Today I will regale you with a tale of perseverance, triumph over the odds, but mostly a tale of laziness that was enabled by the Rust programming language.

When I was in college I was in the Biology/Chemistry program. I didn't really care for Biology, Chemistry was my jam. I knew I wanted to do something involving the biological sciences after college though. As a part of my program a requirement was the Anatomy and Physiology (A&P) course. It had a lot of memorization. I hated memorization and wanted nothing to do with it. I knew that for what I wanted to do with my life, memorizing A&P terms was going to be a distraction, so I went to my program's director and asked what it would take to skip that requirement.

I thought he would say "Nope." but I couldn't lose anything by trying. So I asked, and he answered. And what an answer it was! I could swap out my single Anatomy and Physiology course for a Calculus III and Physical Chemistry (P-Chem) course. I didn't know what I was getting into with Calc III but I—and everyone in the program knew—that P-Chem was the hardest course. So my option was suffer through A&P or take the hardest course plus a bonus math course.

I took the deal, suffered through P-Chem so I wouldn't have to do a bunch of memorization I saw no value in. In the end, I regret nothing. I say that to say this: that's the kind of person that will go on a year long detour into another programming language to avoid a 5 minute job.

And now that the stage's been set, let's get back to the show!

Last year around this time, I was in the process of converting my blog from being built by Jekyll to being powered by Zola. I had been following—with some interest—the happenings in the Rust world, and a blog has always been a good way for me to test the waters of a language. You could say it's kind of my thing.

First I learned HTML: using Apache Server Side Includes (yes, this is how I made my first "CMS"). Then PHP: using Wordpress, then Drupal. Then Ruby: using Octopress, then Jekyll. Then Javascript (React): to use Gatsby (on a different site). And finally, learning Rust: via Zola.

In the process of that conversion, I had a contact page created by the Zola theme that I was using. Alas, my blog had never supported a contact page (or any method of communicating with me besides twitter). I had the infrastructure to do so, just not the will. In fact the GatsbyJS site I created did have form submission, powered by a PHP backend instead of a NodeJS backend (because why rewrite something in a new language when you have existing functionality, amirite?).

Anyway! As I thought about the work needed, I decided I'd rather write a form submission backend in Rust instead of deal with the vagaries of the PHP system.

Here's the kicker though. The script was already written. It was already in place on the server. All I would have had to do was change the global PHP configuration to account for the script's location (each script's location needs to be added to the config because willy nilly access to my server by scripts is strictly forbidden).

There was just one hitch, I didn't know Rust! I was familiar with the syntax of the language through my dalliance with Zola, but I really didn't understand it. However, what I did know of the language convinced me that if I did learn, it would be better than the current cycle of:

  • Add PHP script to server in BSD jail
  • Modify jail's PHP config to look in location of script
  • Ensure that no insecure options are enabled
  • Ensure that changes for this script do not affect existing scripts
  • Debug in production (YOLO!)
  • Modify reverse proxy jail to look for new PHP backend

In all, it may have been about half a day's work. Or, it could have been a quick, less rigorous, 5 minute task where I dealt with problems as they arose. But that idea is what really doomed PHP as an option here; the ease with which I could do something that is poor practice. I was already debugging the submission script in production, where would the madness end!?

There would be downsides to doing this in Rust. A PHP script would be a few kb in size, a Rust application to do the same likely many Mb. But the more I thought it through, the less important this seemed. After the Rust app was built, the toolchain could be deleted and the app would still run. I know because I did it. After the PHP script was written you couldn't just delete the PHP runtime though. Ultimately Rust was the more lightweight choice (if that mattered to me).

If I wanted to make changes I would have to compile and deploy a new binary. But this, while adding more time, was also beneficial. I could more easily get a Rust environment set up on my development mac laptop than I could for PHP.

And then there was the resource usage. The Rust app takes a while to compile on my server (with limited resources)! But after launch, it uses up much less of those resources than the PHP script.

Ultimately, this was a good project for learning Rust, or at least applying the Rust I had learned. Having finished it, I can again say "I regret nothing" (except staying up too late).

The code for my little rust backend—formulate1—is completely open source and available if you'd like to take it for a spin. Just rename the Rocket.toml.template file to Rocket.toml, modify the test email addresses and deploy to your server! To modify the settings like which port to bind on, etc see the excellent Rocket documentation.

Want to comment? @reply to @opinion8d_logic on twitter with the hashtag #learnedrust. OR hit me up on that contact page. ;-)

1

Formulate. verb. to create or devise methodically (I'd say being over a year in the making counts). To express in a concise or systematic way (I think it's pretty concise thanks to rust and Rocket doing most of the heavy lifting).