axol 0.2.0

Axol Web Framework
#![allow(dead_code)]

use std::net::SocketAddr;

use axol::{Router, Server};
use tokio::task::JoinHandle;

/// A router served on an ephemeral port.
///
/// Each test gets its own port, so tests may run concurrently. The listener is bound before
/// [`spawn_router`] returns, so no sleep is needed before issuing requests.
pub struct TestServer {
    addr: SocketAddr,
    handle: JoinHandle<()>,
}

impl TestServer {
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    /// Builds an `http://` URL for `path`, which should start with `/`.
    pub fn url(&self, path: &str) -> String {
        format!("http://{}{path}", self.addr)
    }

    /// Builds a `ws://` URL for `path`, which should start with `/`.
    pub fn ws_url(&self, path: &str) -> String {
        format!("ws://{}{path}", self.addr)
    }
}

impl Drop for TestServer {
    fn drop(&mut self) {
        self.handle.abort();
    }
}

pub async fn spawn_router(router: Router) -> TestServer {
    let server = Server::bind("127.0.0.1:0".parse().unwrap(), router)
        .await
        .expect("bind failure");
    let addr = server.local_addr().expect("no local addr");
    let handle = tokio::spawn(async move {
        server.serve().await.expect("server failed");
    });
    TestServer { addr, handle }
}