trillium-rs / trillium

Trillium is a composable toolkit for building internet applications with async rust
https://trillium.rs
Apache License 2.0
341 stars 18 forks source link

Bug report for `trillium-server-common`: Unexpected panic when binding fails #674

Open qvignaud opened 3 months ago

qvignaud commented 3 months ago

Describe the bug Currently the server Server::build_listener implementations (both unix and not(unix)) panics when the binding fail for any reason.

To Reproduce Steps to reproduce the behavior:

  1. Launch any app using trillium with a given host/port config that is not available on the machine
  2. Panics occur and app stop

Expected behavior To not crash but either returning immediately and/or providing a way to programmatically handle this case (like a new entry in Config like with_binding_failure_handler or other way to not break the API by changing the run/run_async return type.

At least a precision in the doc that run/run_async may panic in some cases would be nice.

Output

thread 'main' panicked at /home/quentin/.cargo/registry/src/index.crates.io-6f17d22bba15001f/trillium-server-common-0.4.7/src/server.rs:64:68:
called `Result::unwrap()` on an `Err` value: Os { code: 98, kind: AddrInUse, message: "Address already in use" }

Additional context I'm using Trillium for inner implementation of HTTP server in Mélodium language, for which crashing because of binding failure is not a admissible behavior.

Circumvent Actually the way to prevent this is to create the binding by ourselves and then give it to the config. This will make the Server::build_listener implementation using the given (already bound) listener instead of doing it with possible panics.

Before:

trillium_async_std::config()
    .with_port(port)
    .with_host(host)
    .run_async(router)
    .await

After:

match async_std::net::TcpListener::bind((host, port)).await {
    Ok(listener) => trillium_async_std::config()
      .with_prebound_server(listener)
      .run_async(router)
      .await,
    Err(err) => {
        // Manage the error
    }
}