How to send 200 http status before any async code in hyper?

I'm trying to make a very simple http hyper server, since all the other frameworks (actix, warp, rocket, ...) have too much bloat that I won't use, and take 5 or more secs to recompile.

The problem is simple: send a 200 http response before executing any async code. This response is an acknowledgment that I the server successfully received the request.

I'm a rust noob, coming from the js world, and with express is as easy as doing the following:

router.post('/', async (req, res) => {

    res.end()

    // ....
    // after ending response, parse request and do some actions based on
    // the json body.
    // ....
})

I've been reading and trying with hyper to get this exact behaviour, but I'm not sure how to do it. Let's supose I had the following code:

use hyper::service::{make_service_fn, service_fn};
use hyper::{body, Body, Method, Request, Response, Server};
use std::convert::Infallible;
use std::net::SocketAddr;

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug)]
pub struct Notification {
    resource: String,
    user_id: usize,
}

pub async fn handle_notification(notification: Notification) {
    println!("Handling {:#?}", notification);

    // Some io operations will occur, this is for a simulation.
    std::thread::sleep(std::time::Duration::from_secs(1));
}

async fn handle_requests(
    req: Request<Body>,
) -> Result<Response<Body>, hyper::Error> {
    let response = Response::default();

    let method = req.method();
    let uri = req.uri().path();

    match (method, uri) {
        (&Method::POST, "/notifications") => {
            let body = body::to_bytes(req.into_body()).await?.to_vec();
            handle_notification(
                serde_json::from_slice::<Notification>(&body).unwrap(),
            ).await;
        }
        _ => {}
    };

    Ok(response)
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 8080));

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

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

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

How can I send an 200 http status to the client before handling the notification? Ignore security details (max body size, ...), this api is supposed to be available only to a single web service.

First, don't use std::thread::sleep. Read this article for why.

As for how to run code after completing the request: Just use tokio::spawn to spawn it as an independent task. It will run in the background.

4 Likes

Hey alice! Glad to see you answering me again :smiley:

That should do it! Thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.