actix-web icon indicating copy to clipboard operation
actix-web copied to clipboard

Server does not start when `spawn`ed

Open rollandjb opened this issue 3 years ago • 0 comments

Your issue may already be reported!

I have searched the issue tracker.

Expected Behavior

According to the documentation here:

[...]The Server must be awaited or spawned to start processing requests [...]

Current Behavior

It seems that spawning the server does not start the server

Possible Solution

I have insufficient rust experience to offer suggestions

Steps to Reproduce (for bugs)

This code demonstrates the problem. See context below for explanation.

use std::{
    sync::mpsc::{self, Sender},
    thread,
};

use actix_web::{
    self, get,
    rt::System,
    web::{self},
    App, HttpRequest, HttpServer,
};
use anyhow::{Error, Result};

#[actix_web::main]
async fn main() -> Result<()> {
    //
    // run the server and wait to receive the secret from the handler
    let secret = run_http_server().await?;

    println!("{}", secret);
    Ok(())
}

struct AppState {
    tx: Sender<String>,
}

#[get("/")]
async fn index(req: HttpRequest, data: web::Data<AppState>) -> String {
    println!("==> handler for {} has started...", req.uri());
    let _ = &data.tx.send(String::from("the secret is 42 or 'xyzzy'"));
    format!("Hello, world!\n")
}

async fn run_http_server() -> Result<String> {
    let (tx_result, rx_result) = mpsc::channel();

    let server = HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(AppState {
                tx: tx_result.clone(),
            }))
            .service(index)
    })
    .shutdown_timeout(60)
    .bind("127.0.0.1:4242")?
    .run();

    //
    // ask user to call the server
    println!("please run the cmd 'curl http://127.0.0.1:4242' to get the secret");

    let server_handle = server.handle();

    //
    // this starts the http server
    let _server_task = thread::spawn(move || System::new().block_on(server));   // A

    //
    // neither of these start the http server
    // let _server_task = rt::spawn(server);                                    // B
    // let _server_task = rt::spawn(async move { server.await });               // C

    //
    // Wait for the result to be delivered
    let values = rx_result.recv();

    //
    // Stop the server
    server_handle.stop(true).await;

    //
    // return the secret sent from the handler
    values.map_err(|e| Error::new(e))
}


  1. Add actix-web and anyhow crates to project
  2. Run with cargo run
  3. Run the command curl http://127.0.0.1:4242 in a terminal
  4. Observe the secret is received as expected
  5. Comment out line A and uncomment either of B or C
  6. Observe that the handler does not run

Context

I am trying to run a temporary http server in the background and receive information sent from a handler called on that server.

Your Environment

I am running an development in vs code on a MacBook Pro M1 Max

  • Rust Version (I.e, output of rustc -V): rustc 1.62.1 (e092d0b6b 2022-07-16)
  • Actix Web Version: 4.1.0

rollandjb avatar Aug 12 '22 07:08 rollandjb