Estimated time: 1 day
The current situation regarding HTTP in Rust ecosystem can be grasped quite well in the "Web programming" section of "Awesome Rust" and in the "Web Frameworks", "HTTP Clients" and "Lower Web-Stack" topics of "Are we web yet?". Of course, most of them use async I/O.
There are few core crates, providing general-purpose HTTP implementation, powering the whole variety of web frameworks and HTTP clients in Rust ecosystem.
The most prominent and mature one is, of course, the hyper
crate (built using tokio
). Almost all web frameworks of Rust ecosystem are built on top of it.
The main alternatives are:
async-h1
, powering theasync-std
ecosystem for HTTP.actix-http
, powering theactix-web
ecosystem.
For more details, read through the following articles:
While hyper
provides its own server implementation, using it directly can feel quite low-level and unergonomic, due to its nature. Naturally, there are numerous web frameworks built on top of hyper
, which provide high-level, ergonomic and friendly interface. The most notable are:
axum
- a web application framework that focuses on ergonomics and modularity, and provides macro-free request routing (yet ergonomic and declarative), simple and predictive error-handling, and leverages full advantage of thetower
andtower-http
ecosystem of middleware, services, and utilities.warp
- a super-easy, composable, web server framework for warp speeds, built around the "everything is aFilter
" concept.rocket
- a web framework, aims to be fast, easy, and flexible while offering guaranteed safety and security where it can, and, importantly, aiming to be fun (accomplishing this by ensuring that you write as little code as needed to accomplish your task).poem
- a full-featured and easy-to-use web framework, focusing on providing all the capabilities (like i18n) out-of-the-box.salvo
- a powerful and simple web server framework, adopting HTTP/3 implementation.
For those who prefer async-std
ecosystem, the definitive choice (and the single one, at the moment) is the tide
crate.
All the web frameworks above inherit the work-stealing from the asynchronous runtime they're run on, and so, require the proper synchronization (being Send
) from user-provided HTTP request handlers, which may introduce an unnecessary or undesired overhead. That's why actix-web
crate was designed and implemented specifically with this consideration in mind (to avoid work-stealing), being built on top of actix-rt
crate (leveraging thread-per-core model), and thus, not requiring any synchronization in its request handlers (allowing !Send
Future
s). Also, actix-web
, at the time, was the first mature and production-ready web framework in Rust ecosystem, possessing a top of "TechEmpower Web Framework Benchmarks".
For better understanding and familiarity with HTTP servers in Rust, read through the following articles:
- Official
actix-web
crate docs - Official
actix-web
crate guides: Server - Official
axum
crate docs - Official
warp
crate docs - Official
rocket
crate docs - Official
poem
crate docs - Official
salvo
book - Official
tide
crate docs - Official
hyper
crate guides: Server
Similarly to a server, while hyper
provides its own client implementation, using it directly can feel quite low-level and unergonomic. So, the "default choice" HTTP client (and mostly used) in Rust ecosystem is the reqwest
crate, built on top of hyper
.
isahc
crate, as an alternative, is a runtime-agnostic wrapper (with major focus on being practical and ergonomic) around the famous cURL library.
For simple and trivial scenarios, where an asynchronous runtime is redundant and/or low overhead is preferred, the viable alternative is the ureq
crate.
For async-std
ecosystem, the main crate is surf
, which is, however, not restricted to async-std
only, and is able to use alternative backends: cURL (via isahc
), hyper
, WASM (via browser's window.fetch
API).
For actix-web
ecosystem, the meaningful option would be the awc
crate, which supports WebSocket connections out-of-the-box (while most other HTTP clients lacks that).
For better understanding and familiarity with HTTP clients in Rust, read through the following articles:
- Official
reqwest
crate docs - Joshua Mo: Writing a Web Scraper in Rust using Reqwest
- Official
isahc
crate docs - Official
ureq
crate docs - Official
surf
crate docs - Official
awc
crate docs - Official
hyper
crate guides: Client
Many HTTP clients and servers in Rust lack a built-in WebSocket implementation. Therefore, the tungstenite
crate was created, providing a barebone and agnostic WebSocket implementation. Crates, like async-tungstenite
and tokio-tungstenite
, provide the actual ready-for-use client/server implementation for the desired ecosystem and asynchronous runtime.
For actix-web
ecosystem, the idiomatic solution is the actix-web-actors::ws
module, providing implementation in a form of actor (via actix
).
For better understanding and familiarity with WebSocket implementations in Rust, read through the following articles:
- Official
tungstenite
crate docs - Official
async-tungstenite
crate docs - Official
tokio-tungstenite
crate docs - Official
actix-web-actors::ws
module docs
Rework the task from the previous step in a client-server architecture. It should consist of a CLI client and a server daemon, and utilize the "thin client" approach:
- CLI client does nothing except sending commands "as is" to the server and rendering its responses.
- Server daemon, having a single HTTP endpoint, does all the parsing and executing of commands sent by the CLI client.
After completing everything above, you should be able to answer (and understand why) the following questions:
- What is HTTP? What does HTTP/2 imply? What does HTTP/3 imply?
- How do work-stealing and thread-per-core paradigms affect programming a web server in practice? Which one is better and when? When does this question (choosing) become meaningful, in practice?
- What are common crates for making HTTP requests in Rust? Which trade-offs do they have?
- What is WebSocket? How is it used and when? How does it work, in a nutshell?