FlorianUekermann / rustls-acme

Apache License 2.0
144 stars 28 forks source link

Compatibility with tokio-based warp library #35

Closed bartnv closed 1 year ago

bartnv commented 1 year ago

First of all: thank you for this nice library with a well though-out interface. I would really like to use it within a project using the tokio-based warp library (https://docs.rs/warp/). The problem I run into is that this library only supports running on a stream of incoming connections (https://docs.rs/warp/latest/warp/struct.Server.html#method.run_incoming) with trait bounds for tokio::io::{AsyncRead,AsyncWrite}. I can't use a custom acceptor like in the high_level_tokio example to run the compat() method, so I'm stuck for now.

Example of the code I have so far:

use tokio::{ fs, sync, net::TcpListener };
use tokio_stream::wrappers::TcpListenerStream;
use tokio_util::compat::TokioAsyncReadCompatExt;
use futures_util::stream::{ StreamExt, TryStreamExt };
use rustls_acme::{ AcmeConfig, caches::DirCache };

tokio::spawn(async move {
    let tcp_listener = TcpListener::bind(sa).await.unwrap();
    let tcp_incoming = TryStreamExt::map_ok(TcpListenerStream::new(tcp_listener), |tcp_stream| { tcp_stream.compat() });
    let mut tls_incoming = AcmeConfig::new(["example.com"])
        .contact_push("mailto:mail@example.com")
        .cache(DirCache::new("./tmp"))
        .incoming(tcp_incoming);
    let index = warp::path::end().map(|| warp::reply::html(INDEX_FILE));
    warp::serve(index).run_incoming(tls_incoming).await;
});

This fails to compile with:

the trait bound `rustls_acme::futures_rustls::server::TlsStream<Compat<tokio::net::TcpStream>>: tokio::io::AsyncRead` is not satisfied

If I change the last line to:

warp::serve(index).run_incoming(tls_incoming.compat()).await;

I get:

error[E0599]: the method `compat` exists for struct `rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>`, but its trait bounds were not satisfied
   --> src/control.rs:226:81
    |
226 |               warp::serve(index.or(icon).or(websocket)).run_incoming(tls_incoming.compat()).await;
    |                                                                                   ^^^^^^ method cannot be called on `rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>` due to unsatisfied trait bounds
    |
   ::: /home/sargeth/.cargo/registry/src/github.com-1ecc6299db9ec823/rustls-acme-0.5.1/src/incoming.rs:13:1
    |
13  | / pub struct Incoming<
14  | |     TCP: AsyncRead + AsyncWrite + Unpin,
15  | |     ETCP,
16  | |     ITCP: Stream<Item = Result<TCP, ETCP>> + Unpin,
...   |
25  | |     tls_accepting: FuturesUnordered<Accept<TCP>>,
26  | | }
    | | -
    | | |
    | |_doesn't satisfy `_: TokioAsyncReadCompatExt`
    |   doesn't satisfy `_: tokio::io::AsyncRead`
    |
    = note: the following trait bounds were not satisfied:
            `rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: tokio::io::AsyncRead`
            which is required by `rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: TokioAsyncReadCompatExt`
            `&rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: tokio::io::AsyncRead`
            which is required by `&rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: TokioAsyncReadCompatExt`
            `&mut rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: tokio::io::AsyncRead`
            which is required by `&mut rustls_acme::Incoming<Compat<tokio::net::TcpStream>, std::io::Error, futures_util::stream::MapOk<TcpListenerStream, [closure@src/control.rs:212:91: 212:127]>, std::io::Error, std::io::Error>: TokioAsyncReadCompatExt`

I'm not sure this can be solved reasonably within this library, but wanted to reach out just in case. Superficially it seems to me to be similar to the problem that came up with axum (https://github.com/FlorianUekermann/rustls-acme/issues/27), but it might be more complicated.

FlorianUekermann commented 1 year ago

Thank you for the report. I'm recovering from the holidays today. But I'll take a look at this tomorrow. I'm sure we'll find a solution.

FlorianUekermann commented 1 year ago

I published 0.5.2 with better tokio helpers and a warp example. You could have used TryStreamExt::map_ok with .compat(), but I think it makes sense to provide nice helper methods and types for tokio.

Does this work for you?

bartnv commented 1 year ago

This works great, thanks a lot! Indeed nice to have these helper methods for commonly used libraries.