Web frameworks in Rust
Posted 2020-09-09 20:48. Tagged web, development, rust.
When doing a web application server, one of the first things to decide is which “web application framework” or “request handler library” to use. In Rust, there are more alternatives for that question than in most programming languages, and anyone who has ported some code from tomcat jsp to play framework or from flask to django may dread making the wrong choice. On the other hand, Rust being very strict on static typing makes it very easy to do major refactorings, and I have switched existing projects from iron to nickel to gotham to warp myself without too big problems.
This page collects some of my personal thoughts on each alternative as of September 2020.
The async
story in Rust is still rather new; the language support is
great, but some things is still not standardized, so there are two
main libraries providing run-time and I/O support.
One is async-std and the other tokio.
I have examples of many of these frameworks in the ructe project. See also Are we web yet?, a community-driven sometimes updated status page for writing web application servers in Rust.
That said, over to the alternatives:
Rocket
rocket (version 0.4.5, May 30, 2020), docs, homepage.
One of the “flagships” for web apps served by Rust. Requires the unstable “nightly” compiler, but is aiming to work on stable rust from the upcoming rocket 0.5 release.
Combines typed arguments with annotations for binding url parameters, post data, etc.
Warp
warp (version 0.2.5, Aug 31, 2020), docs.
Based on tokio and an “everything is a filter” philosophy. Filters collect arguments from e.g. the url or cookies, which they send on the the next filters, including the actual handler. So if the handler wants e.g. en integer from the url or a valid authenticated session from a cookie, it can take those as arguments and never get called if they are absent or invalid.
This is the framework I currently use for rphotos and fanrs.
Tide
tide (version 0.13.0, Jul 31, 2020), docs.
Uses the async-std family of async libraries.
Each handler get a “Request<T>
” from which parameters can be
extracted by name.
Maybe not as pure (and optimized) as the warp way, but on the other
hand it gives an easier way to handle special demands in each handler,
while keeping the most common way as simple as a “?
” operator on
the extractor.
The “T
” can be used for an application struct, providing access to a
database pool or any other shared resources.
Gotham
gotham (version 0.5.0, Sep 6, 2020), docs, homepage.
Each handler takes a State
and returns a (State, Response)
tuple.
The State provides access both to shared application data and to
request parameters.
Parameters are extracted by type, rather than by name, requiring some
rather verbose code while still having important name strings hidden
in a layer of abstraction.
Actix web
actix-web (version 2.0.0 December 25, 2019, 3.0 in beta), docs, homepage.
Based on the Actix actor framework rather than async-std or tokio. Routing and parameter extraction is by name, similar to tide.
Tower web
tower-web (version 0.3.7 Apr 10, 2019), docs, repo.
Annotation-driven in a way similar to Rocket, but has been working on
stable Rust for a long time.
On the other hand, it has not seen much recent activity and still uses
a version of tokio
that predates the async
/await
language
support.
Iron and nickel
iron (version 0.6.1, Aug 14, 2019), docs.
nickel (version 0.11.0, Jan 15, 2019), docs.
These two are pretty much abandoned today, but deserves a honorable mention for being two of the first frameworks to demonstrate the potential of Rust in a web server.
Summary
If I choose a framework for a serious project starting now, I choose either warp or tide. That may change in the future, but if it does I’m confident that the strict type checking in Rust will make it easy to switch.
Have I missed your favorite framework? Or is my preference just wrong? Please write a comment and tell me!
Comments
Write a comment