Context in Rust

Here’s the translation of the Go code to Rust, along with explanations in Markdown format suitable for Hugo:

In the previous example, we looked at setting up a simple HTTP server. HTTP servers are useful for demonstrating the usage of Context for controlling cancellation. A Context carries deadlines, cancellation signals, and other request-scoped values across API boundaries and threads.

use std::time::Duration;
use warp::Filter;
use tokio::time::sleep;

async fn hello(req: warp::Request) -> Result<impl warp::Reply, warp::Rejection> {
    println!("server: hello handler started");

    // In Rust, we use tokio's spawn to create a new task (similar to a goroutine)
    let task = tokio::spawn(async move {
        // Simulate some work
        sleep(Duration::from_secs(10)).await;
        "hello\n"
    });

    // Use tokio's select! macro to wait for either the task to complete or a cancellation
    tokio::select! {
        result = task => {
            println!("server: hello handler ended");
            Ok(result.unwrap())
        }
        _ = tokio::signal::ctrl_c() => {
            println!("server: request canceled");
            Err(warp::reject::not_found())
        }
    }
}

#[tokio::main]
async fn main() {
    // Register our handler on the "/hello" route, and start serving
    let routes = warp::path("hello").and_then(hello);

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

Run the server in the background:

$ cargo run &

Simulate a client request to /hello, hitting Ctrl+C shortly after starting to signal cancellation:

$ curl localhost:8090/hello
server: hello handler started
^C
server: request canceled
server: hello handler ended

In this Rust version:

  1. We use the warp crate for the HTTP server, which is built on top of tokio.
  2. Instead of context.Context, we use Rust’s async/await features and tokio’s tasks for managing concurrency.
  3. The select! macro is used to wait for either the task to complete or a cancellation signal (Ctrl+C).
  4. Error handling is done through Rust’s Result type and warp’s rejection mechanism.

While Rust doesn’t have an exact equivalent to Go’s context.Context, the combination of tokio’s tasks and the select! macro provides similar functionality for managing cancellation and timeouts in asynchronous operations.