I have two similar functions which run an HTTP server. run_http_server1()
compiles without errors, but run_http_server2()
has a generic specification which I cannot declare correctly and so I get compilation errors.
How do I declare the second function? Why does my declaration not work?
#[tokio::main]
async fn main() {
// run_http_server1().await;
run_http_server2::<MyService>().await;
}
async fn run_http_server1() {
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3333));
let make_service = hyper::service::make_service_fn(|_conn| async {
let svc = MyService::new("hello, world!".to_string());
Ok::<_, std::convert::Infallible>(svc)
});
let server = hyper::Server::bind(&addr).serve(make_service);
server.await.expect("server failed");
}
async fn run_http_server2<S>()
where
S: tower::Service<hyper::Request<hyper::Body>> + 'static + Send + Factory,
<S as tower::Service<hyper::Request<hyper::Body>>>::Error: Sync + Send + std::error::Error,
<S as tower::Service<hyper::Request<hyper::Body>>>::Future: std::marker::Send,
{
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3333));
let make_service = hyper::service::make_service_fn(|_conn| async {
let svc = S::new("hello, world!".to_string());
Ok::<_, std::convert::Infallible>(svc)
});
let server = hyper::Server::bind(&addr).serve(make_service);
server.await.expect("server failed");
}
#[derive(Clone)]
struct MyService {
s: String,
}
trait Factory {
fn new(s: String) -> Self;
}
impl Factory for MyService {
fn new(s: String) -> MyService {
MyService { s }
}
}
impl tower::Service<hyper::Request<hyper::Body>> for MyService {
type Response = hyper::Response<hyper::Body>;
type Error = std::convert::Infallible;
type Future = futures::future::Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(
&mut self,
_cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
std::task::Poll::Ready(Ok(()))
}
fn call(&mut self, _req: hyper::Request<hyper::Body>) -> Self::Future {
let resp = hyper::Response::new(hyper::Body::from(self.s.clone()));
futures::future::ready(Ok(resp))
}
}
Here are my dependencies from Cargo.toml:
[dependencies]
hyper = { version = "0.14", features = ["full"] }
rustls-pemfile = "0.3"
tokio = { version = "1", features = ["full"] }
tokio-rustls = "0.23"
tower = { version = "0.4", features = ["make"] }
tracing = "0.1"
tracing-subscriber = { version="0.3", features = ["env-filter"] }
futures-util = "0.3"
futures = "0.3"
rustls = "0.20"
The error
Compiling trial v0.1.0 (/home/alek/projects/rust/trial)
error[E0271]: type mismatch resolving `<<S as Service<Request<Body>>>::Future as futures::Future>::Output == Result<Response<_>, _>`
--> src/main.rs:32:45
|
32 | let server = hyper::Server::bind(&addr).serve(make_service);
| ^^^^^ expected associated type, found struct `Response`
|
= note: expected enum `Result<<S as Service<Request<Body>>>::Response, <S as Service<Request<Body>>>::Error>`
found enum `Result<Response<_>, _>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `futures::Future` for `hyper::proto::h2::server::H2Stream<<S as Service<Request<Body>>>::Future, _>`
= note: required because of the requirements on the impl of `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` for `hyper::common::exec::Exec`
error[E0271]: type mismatch resolving `<S as Service<Request<Body>>>::Response == Response<_>`
--> src/main.rs:32:45
|
32 | let server = hyper::Server::bind(&addr).serve(make_service);
| ^^^^^ expected associated type, found struct `Response`
|
= note: expected associated type `<S as Service<Request<Body>>>::Response`
found struct `Response<_>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `hyper::service::http::HttpService<Body>` for `S`
error[E0277]: the trait bound `hyper::common::exec::Exec: hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` is not satisfied
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ the trait `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` is not implemented for `hyper::common::exec::Exec`
|
= help: the following implementations were found:
<hyper::common::exec::Exec as hyper::common::exec::ConnStreamExec<F, B>>
= note: required because of the requirements on the impl of `futures::Future` for `hyper::server::conn::spawn_all::NewSvcTask<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>`
= note: required because of the requirements on the impl of `hyper::common::exec::NewSvcExec<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>` for `hyper::common::exec::Exec`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure@src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `<S as Service<Request<Body>>>::Response == Response<_>`
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ expected struct `Response`, found associated type
|
= note: expected struct `Response<_>`
found associated type `<S as Service<Request<Body>>>::Response`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `hyper::service::http::HttpService<Body>` for `S`
= note: required because of the requirements on the impl of `hyper::common::exec::NewSvcExec<AddrStream, impl futures::Future, S, hyper::common::exec::Exec, hyper::server::conn::spawn_all::NoopWatcher>` for `hyper::common::exec::Exec`
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure@src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `<<S as Service<Request<Body>>>::Future as futures::Future>::Output == Result<Response<_>, _>`
--> src/main.rs:33:5
|
33 | server.await.expect("server failed");
| ^^^^^^^^^^^^ expected struct `Response`, found associated type
|
= note: expected enum `Result<Response<_>, _>`
found enum `Result<<S as Service<Request<Body>>>::Response, <S as Service<Request<Body>>>::Error>`
= help: consider constraining the associated type `<S as Service<Request<Body>>>::Response` to `Response<_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: required because of the requirements on the impl of `futures::Future` for `hyper::proto::h2::server::H2Stream<<S as Service<Request<Body>>>::Future, _>`
= note: required because of the requirements on the impl of `hyper::common::exec::ConnStreamExec<<S as Service<Request<Body>>>::Future, _>` for `hyper::common::exec::Exec`
= note: 1 redundant requirements hidden
= note: required because of the requirements on the impl of `futures::Future` for `Server<AddrIncoming, hyper::service::make::MakeServiceFn<[closure@src/main.rs:27:56: 30:6]>>`
note: required by `futures::Future::poll`
--> /home/alek/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:99:5
|
99 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
error: could not compile `trial` due to 5 previous errors