Rust is an emerging programming language with lots of popularity. More and more companies are adopting to rust every next day. The reason being rust is not your usual generic programming language. It brings something new to the table, that very few other popular languages do. Namely Ownership, Borrowing and Lifetimes. Which ultimately can make learning Rust intimidating. but once you grasp these core concepts in rust, it enables you to write fast and safe apps with fearless concurrency.

In other words, in rust, unlike C or C++ you don’t need to manage memory manually. Rusts compiler is smart enough to understand which variable gets freed, at what time Without using a GC. Features like these, have enabled rust developers to write fast applications without compromising memory safety, giving birth to high quality software and tools of modern age. This list of modern age tools consist of everything from an Operating Systems, to embedded devices, to cross-platform GUI libs to cloud native stuff, and it’s evergrowing

In this list, you will notice a huge section on HTTP libs. Rust has made a huge impact in Web domain, mainly because of the aforementioned traits of rust. Because rust provides fearless concurrency, devs are finally able to concentrate on features and let compiler worry about the memory, giving birth to libraries like actix-web providing a flawless performance of whooping 600k req/s on benchmarks, making it one of the fastest web application server on earth.

And this is exactly what we are going to look at today. Managing few Rust communities on social media like Telegram and Reddit I usually notice a common question about web “Which Web framework I should use?”, let’s try to answer this question with taking an overview of famous HTTP libs. Note that although I will try to explain the libs according to their docs/readme’s only, the review will also contain some on my thoughts as well. If I mention x framework is bad you don’t have to agree with me, that’s just my opinion, but I will SURELY love to hear your opinion. That being said, no framework fits all use cases. This post only tries to cover what these frameworks are, and not ‘Should I use X or Y’. Which one you should use, totally depends on thousands of things like how well you know rust, how much time you have to develop your app, how large is your team, what performance you want, etc etc. So evaluate all these frameworks yourself, and pick whichever one you are comfortable with.

Hyper

It’s basically impossible to not-mention hyper when it comes to HTTP implementations in Rust. Hyper is an old (mature), fast and correct HTTP framework in rust. You can call it father of many major frameworks today. It’s like nodejs’s raw http module. It provides you with basic APIs to start a server and process HTTP requests and responses, it’s your job to figure out how to do the routing and etc stuff. Overall, it’s fast but not really a good choice if you are looking for an enterprise grade full fledged HTTP framework. Good thing about Hyper is it’s very slim, thus fast, supports HTTP/1 and HTTP/2 and also has Async API. So it’s easy to write HTTP frameworks on top of Hyper. which is what many frameworks do.

TL;DR: it’s an http framework to create http framework!

A simple hyper service look like this:

let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

let make_svc = make_service_fn(|_conn| async {
    Ok::<_, Infallible>(service_fn(handle))
});

let server = Server::bind(&addr).serve(make_svc);

if let Err(e) = server.await {
    eprintln!("server error: {}", e);
}

If you notice, it’s a bit too low level for an HTTP framework. I personally wouldn’t use it for making production ready services.

Actix

Technically Actix is the name of an actor framework and the name of the HTTP lib that was written on top of actix is actix-web. But it’s pretty common to call it just actix when you are referencing it in terms http framework. Actix is one the fastest web framework as mentioned above. Note that these are just benchmarks and if you have been developing web apps for a good amount of time, you know these benchmarks don’t mean much in real life. They just represent how far you can push a framework to its limits. Big giants like Instagram and Dropbox survived just fine with Python - one of the worlds slowest language in the world. So don’t let these benchmark affect your decision blindely (Of course the faster the better but it comes with different costs).

Actix has seen some drama in open source community already, causing the owner to delete the repository until he transferred the ownership to someone else. Now it’s being maintained by community, and it’s being actively maintained. Actix mainly focuses on being a pragmatic framework, without compromising the speed at all. At least that was it’s goal when the original Author started Writting it. And we can pretty much see that they have achieved their goal. Writing a simple hello world service in Actix looks like this:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(web::resource("/").to(|| async { "Hello world!" })
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

NOTE recent version of actix also supports rocket like API for creating routes, i.e. with proc macros

It’s clear that this is much better than Hyper. Note that this is just an example with Hello World. Actix has multiple ways of doing routing and writing services. you should definitely check out the docs for more information.

Actix is a complete production ready framework. you will almost never feel stuck because of incomplete APIs etc. BUT, the only problem I have seen with Actix so far is it lacks a good documentation. And the community is not THAT active either. Half of the time you will have to figure your problem out yourself. i.e. How useful Actix will be for you depends on how well you know Rust. Other than that you can build almost any stack web application with actix. Luckily they have created a huge list of examples which you can refer. These examples try to cover most of the general purpose tech stack like databases, graphql, security, ui etc.

Rocket

The next big gun in Rust’s Web ecosystem is Rocket. Most of the time people are always confused between Actix and Rocket. Rocket is also one of the oldest and mature framework in Rust. At the time of writing, Rocket requires nightly version of Rust to run. This is because Rocket uses some APIs that are easy to read and right for end user but are not stable enough in Rust. But this will be solved soon, once these APIs get stabilized.

Also, earlier Rocket user to utilize worker threads to support serving multiple requests at once. This was because at that time Rust didn’t have Async support. but that’s being fixed as well. recent versions of Rocket support Async API as well, and it will be fully migrated to Async ecosystem as far as I know.

A simple hello world program in Rocket looks like this:

#[macro_use] extern crate rocket;

#[get("/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
    format!("Hello, {} year old named {}!", age, name)
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/hello", routes![hello])
}

Personally, I think it’s easiest HTTP framework to use. Just by looking at the code you understand immediately what the code is doing. Say if you want to add one more route for POST, it’s as easy as creating a handler function and adding

#[post(/route)]

on top of it. Luckily, the Documentation is well written, They also have lots of examples lying around which you can refer. The community is active as well. I think the cost of using nighly rust (until it gets stabilized) is worth it if you are getting all these features out of the box. The only downside I see with Rocket is nightly rust and slower performance compared to actix (not slow performance, slower performance than actix it’s still pretty fast).

If you are looking for something to write your app quickly and get done with it, I think Rocket is a good choise.

Tide

Coming from Javascript background, Tide felt like at home to me. Unlike few other frameworks, Tide doesn’t use popular frameworks like Tokio and Hyper. it’s based on async-std which makes it stand out. unsurprisingly, it’s a fully async web framework. it’s API is a lot similar to node’s express framework. which made it very intuitive for me personally. things like ‘to get headers from request’ I could just try printing req.headers and it used to work. which was a big plus for me. With tide your code becomes a bit verbose. ultimately, it comes with a performance cost as well. generally you will see the performance of Tide is comparable to nodejs http. Although this could change in future.

a simple tide hello world program looks like this;

#[async_std::main]
async fn main() -> Result<(), std::io::Error> {
    tide::log::start();  // optional
    let mut app = tide::new();
    app.at("/").get(|_| async { Ok("Hello, world!") });
    app.listen("127.0.0.1:8080").await?;
    Ok(())
}

All of these frameworks are very mature, evolved and tested well. for simple apps like basic CRUD operation, you will almost never feel stuck. for complex things, you may want to look into learning Rust in depth before proceeding (That’s just my opinion).

Warp

Warp, as the name suggests is another very fast HTTP framework, based on hyper. Naturally, it gets all the good features of hyper out of the box. namely: HTTP/1 and HTTP/2, Async, Battle tested for correctness, Speed etc. The first line in their README says “A super-easy, composable, web server framework for warp speeds” I personally disagree with this line but we will see why later. Warp revolves around a concept called “Filters”. It brings something new to the table for creating web apps. traditionally you would declare route, then declare a service fucntion (route handler) for that route, then embed route into webapp and so on. In warp, everything is filters. You create and reuse these filters however you like. That’s what “Composible” in their decription means. Because of these filters you get things like path params, query params, headers, json serialization, multipart support and so many other things out of the box.

A basic hello world server in warp looks like this:

use warp::Filter;

#[tokio::main]
async fn main() {
    // GET /hello/warp => 200 OK with body "Hello, warp!"
    let hello = warp::path!("hello" / String)
        .map(|name| format!("Hello, {}!", name));

    warp::serve(hello)
        .run(([127, 0, 0, 1], 3030))
        .await;
}

Here, you can observe the routing is based on path! macro, which is nothing but a filter. just like the name suggests, after warp has filtered the request that matches /hello/x for you, you can decide what to do with it and so on. Similarly warp has filters for: body, compression, cookies, header, method, path, query and etc.

This filter mechanism makes warp really powerful. Your code becomes declarative and readable. but unfortunately I have had a hard time creating proper apps with warp. The reason behind that could be I am just too dumb to understand it. But think about this, to create ‘composible’ functions, you need to be able to break them down before or at the time of writing your application. which generally I fail to do so. one reason behind it is not having a clear picture of what X route will be doing or so. even if you manage to implement that reusable X route, if something changes and you want remove one filter and apply another etc, it generally affects entire app. Now again, this could be just my own case. so feel free to try warp out yourself. It’s one of the most popular framework for a reason.

Notable mentions:

That should cover the most popular frameworks I could think of in rust for web development. but of course rust doesn’t have just 4 or 5 frameworks. there are many more which I can’t cover in just one blog post. the reason I decided not to cover them thoroughly is most of these frameworks are either not developing at a good pace or their development has abandoned too. or they are just not popular enough yet. In this list I could name a few: