To learn rust I wrote my own HTTP server and JSON parser from scratch. Looking for feedback on how to make it more idiomatic

I've been wanting to learn rust for a while now, and finally got around to actually writing some code. In hacker fashion, I wrote this project to scratch an itch: I accidentally used up all of the bandwidth on my cellphone for the month and no longer had the means of finding out when the next bus would pass by a stop. Public transport in my city have a website that shows this in real time. I used this as an excuse to code something that reads the schedules from their unofficial REST API and send me the info via SMS using my VoIP's REST API.

Code can be found here: https://github.com/gelendir/rtcsms

It's not perfect, but i'm pretty glad I got it working for real. Since this the first time i've done any rust i'd appreciate any feedback on how to make the code more idiomatic, or some answers to the following questions:

  • I was surprised by how much boilerplate I had to write for creating and wrapping custom errors. I imagine this might be easier with the use of a crate, but would there be a simpler approach to my error handling ?
  • I'd like to reduce the friction caused by using String and &str everywhere. I've mainly used String s because it seemed easier for fixing compiler errors, but because of that i've had to sprinkle a lot of .to_string() . I haven't taken the time yet to go over the chapter about lifetimes in the rust book , would that help ?
  • Since i'm parsing HTTP requests myself i'm splitting strings and having to use .next().ok_or(...)? a lot. An easier way of dealing with that ? Maybe i'm just to used to the ease of foo.split(" ")[1] in python
  • Still not sure I completely understand why I need to Box<dyn ReadWrite> to use a tcp or tls socket interchangeably. Is there a way of using those traits without the Box ?

Thanks in advance for any feedback. It took a bit of time before I actually got anything working, but once I got past that it was a pretty interesting experience. Surprisingly, writing the JSON parser wasn't as hard as I expected and once I got all the compiler errors fixed it worked on the first try !

Which is a very common experience when coding in Rust. :sweat_smile: Welcome to the club.

2 Likes

If you plan on having run-time calculated values (e.g., "the error came from: {}", my_error_source), then use String because you need to make sure that the data survives after the closure returns. The way to do that is the stash the dynamic string to the heap.

If you have a static value, just use &str (e.g., "the error came from the proxy server").

And yes, learn about lifetimes. Be patient on yourself, and maybe read a little per day. Eventually, it will make intuitive sense