如何使用 futures “0.3” 和 hyper “0.13.0-alpha.4” 编写一个简单的 Rust 异步代理?
How to write a simple Rust asynchronous proxy using futures "0.3" and hyper "0.13.0-alpha.4"?
我正在尝试通过迁移到 :
来重写代理书 example of Asynchronous Programming in Rust
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"
当前示例将返回的 Future
从 futures 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
的错误:
the trait tower_service::Service<&'a
hyper::server::tcp::addr_stream::AddrStream>
is not implemented for
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
中的实现可能有所不同。
如果您告诉我您的修复方法,我将不胜感激。
通过这个 issue, to create a new service for each connection you need to create MakeService 在 hyper = "0.13.0-alpha.4"
中。您可以使用 make_service_fn
创建带有闭包的 MakeService
。
Also, I cannot use hyper::rt::run
because it might have been implemented differently in 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
}
我正在尝试通过迁移到 :
来重写代理书 example of Asynchronous Programming in Rustfutures-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"
当前示例将返回的 Future
从 futures 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
的错误:
the trait
tower_service::Service<&'a hyper::server::tcp::addr_stream::AddrStream>
is not implemented forhyper::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
中的实现可能有所不同。
如果您告诉我您的修复方法,我将不胜感激。
通过这个 issue, to create a new service for each connection you need to create MakeService 在 hyper = "0.13.0-alpha.4"
中。您可以使用 make_service_fn
创建带有闭包的 MakeService
。
Also, I cannot use
hyper::rt::run
because it might have been implemented differently inhyper = 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
}