【问题标题】:How to write a simple Rust asynchronous proxy using futures "0.3" and hyper "0.13.0-alpha.4"?如何使用期货“0.3”和超“0.13.0-alpha.4”编写一个简单的Rust异步代理?
【发布时间】:2019-11-04 04:16:04
【问题描述】:

我正在尝试通过迁移到 Asynchronous Programming in Rust 本书来重写代理 example

futures-preview = { version = "0.3.0-alpha.19", features = ["async-await"]}`
hyper = "0.13.0-alpha.4"`

来自:

futures-preview = { version = "=0.3.0-alpha.17", features = ["compat"] }`
hyper = "0.12.9"

当前示例将返回的Futurefutures 0.3 转换为futures 0.1,因为hyper = "0.12.9"futures 0.3 的async/await 不兼容。

我的代码:

use {
    futures::future::{FutureExt, TryFutureExt},
    hyper::{
        rt::run,
        service::{make_service_fn, service_fn},
        Body, Client, Error, Request, Response, Server, Uri,
    },
    std::net::SocketAddr,
    std::str::FromStr,
};

fn forward_uri<B>(forward_url: &'static str, req: &Request<B>) -> Uri {
    let forward_uri = match req.uri().query() {
        Some(query) => format!("{}{}?{}", forward_url, req.uri().path(), query),
        None => format!("{}{}", forward_url, req.uri().path()),
    };

    Uri::from_str(forward_uri.as_str()).unwrap()
}

async fn call(
    forward_url: &'static str,
    mut _req: Request<Body>,
) -> Result<Response<Body>, hyper::Error> {
    *_req.uri_mut() = forward_uri(forward_url, &_req);
    let url_str = forward_uri(forward_url, &_req);
    let res = Client::new().get(url_str).await;
    res
}

async fn run_server(forward_url: &'static str, addr: SocketAddr) {
    let forwarded_url = forward_url;
    let serve_future = service_fn(move |req| call(forwarded_url, req).boxed());

    let server = Server::bind(&addr).serve(serve_future);
    if let Err(err) = server.await {
        eprintln!("server error: {}", err);
    }
}

fn main() {
    // Set the address to run our socket on.
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    let url = "http://127.0.0.1:9061";
    let futures_03_future = run_server(url, addr);
    run(futures_03_future);
}

首先,我在run_server 函数中收到server 的此错误:

特征tower_service::Service<&'a hyper::server::tcp::addr_stream::AddrStream> 未实现 hyper::service::service::ServiceFn<[closure@src/main.rs:35:35: 35:78 forwarded_url:_], hyper::body::body::Body>

另外,我不能使用hyper::rt::run,因为它在hyper = 0.13.0-alpha.4 中的实现方式可能不同。

如果您能告诉我您的解决方法,我将不胜感激。

【问题讨论】:

    标签: asynchronous rust async-await future hyper


    【解决方案1】:

    通过这个issue,要为每个连接创建新服务,您需要在hyper = "0.13.0-alpha.4" 中创建MakeService。您可以使用make_service_fn 创建带有闭包的MakeService

    另外,我不能使用hyper::rt::run,因为它在hyper = 0.13.0-alpha.4 中的实现方式可能不同。

    正确,在后台 hyper::rt::run 正在调用 tokio::run,它已从 api 中删除,但目前我不知道原因。您可以自己调用tokio::run 或使用#[tokio::main] 注释来运行您的未来。为此,您需要将tokio 添加到您的货物中:

    #this is the version of tokio inside hyper "0.13.0-alpha.4"
    tokio = "=0.2.0-alpha.6" 
    

    然后像这样更改您的run_server

    async fn run_server(forward_url: &'static str, addr: SocketAddr) {
        let server = Server::bind(&addr).serve(make_service_fn(move |_| {
            async move { Ok::<_, Error>(service_fn(move |req| call(forward_url, req))) }
        }));
        if let Err(err) = server.await {
            eprintln!("server error: {}", err);
        }
    }
    

    main

    #[tokio::main]
    async fn main() -> () {
        // Set the address to run our socket on.
        let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
        let url = "http://www.google.com:80"; // i have tested with google 
    
        run_server(url, addr).await
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-08
      • 2018-01-01
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      相关资源
      最近更新 更多