如何将hyper :: server :: Server存储为结构中的字段?

时间:2019-06-06 00:06:25

标签: rust hyper

我有一个在内部使用hyper的库。我希望用户能够创建一个App,其中包含一个内部Server来处理HTTP连接。

use hyper::server::conn::AddrIncoming;
use hyper::server::Server;
use hyper::service::service_fn_ok;
use std::net::SocketAddr;

pub struct App {
    inner: Server<AddrIncoming, ()>,
}

impl App {
    pub fn new() -> Self {
        let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
        let inner = Server::bind(&addr).serve(|| service_fn_ok(|_req| unimplemented!()));

        App { inner }
    }
}

Playground link

该错误是预期的:

error[E0308]: mismatched types
  --> src/lib.rs:15:15
   |
15 |         App { inner }
   |               ^^^^^ expected (), found closure
   |
   = note: expected type `hyper::server::Server<_, ()>`
              found type `hyper::server::Server<_, [closure@src/lib.rs:13:47: 13:88]>`

虽然没有充分的文档说明,但是Server的第二种类型参数是它使用的MakeService的类型。

我不知道如何用inner类型引用闭包。有什么办法可以使闭合框装起来以使代码编译?有没有办法手动实现MakeService而不是使用闭包?

超级文档引用函数make_service_fn,该函数返回MakeServiceFn,但是该类型不是公共的,因此我不能在inner的类型中使用它。

1 个答案:

答案 0 :(得分:0)

问题是由于类型不匹配。在Rust中,类型参数是结构类型的一部分,因此结构中服务器的类型参数必须与您在结构中定义的参数匹配。就您而言,他们没有。

您的问题有2种解决方案。

将第二个服务器参数的类型参数添加到您的结构中

pub struct App<T> {
    inner: Server<AddrIncoming, T>,
}

现在,您将能够为服务器的第二类型参数创建具有不同类型的应用

查找要创建的服务器的第二个参数的类型

在您的情况下,第二个参数的类型为``,因此您将这样声明结构:

type Service = ?; // This is really hard to find in this case.
pub struct App {
    inner: Server<AddrIncoming, Service>,
}

结论

在您的情况下,我建议您使用第一个参数,因为Server的第二个类型参数的类型很难找到,并且在您的程序开发过程中很可能会发生变化,因此拥有它会容易得多结构上的类型参数。

但是,如果您不知道服务器的类型参数没有实现某些特征,有时您将无法在服务器上使用某些方法,因此可以将这些特征添加到类型参数中,如下所示:< / p>

pub struct App<T: Service> {
    inner: Server<AddrIncoming, T>,
}

建议不要将类型参数放在结构本身上,而应仅将其放在impl块上:

pub struct App<T> {
    inner: Server<AddrIncoming, T>,
}

impl App<T: Service> {
   // Here you'll be able to use the method from Server where T has to be a Service.
}

您还可以对以下功能执行相同的操作:

pub struct App<T> {
    inner: Server<AddrIncoming, T>,
}

fn some_function(app: App<T: Service>) {
   // Here you'll be able to use the method from Server where T has to be a Service
}