配置 Rust 的 Warp 过滤器时遇到问题
Trouble configuring Rust's Warp Filters
我正在尝试设置一个简单的 GET
过滤器,但我无法编译它。
这是我要映射到请求的函数:
pub async fn get_users(reference_counter: Arc<RwLock<MysqlConnection>>) -> Result<impl Reply, Rejection> {
// Get users code here
}
这就是我将函数映射到 main.rs
中的 GET
请求的方式:
#[tokio::main]
async fn main() {
let db_connection = storage::establish_connection();
let lock = RwLock::new(db_connection);
let reference_counter = Arc::new(lock);
let ref_filter = warp::any().map(move || reference_counter.clone());
let get_users = warp::get()
.and(warp::path("users"))
.and(ref_filter.clone())
.and_then(user::get_users);
warp::serve(get_users).run(([127, 0, 0, 1], 3030)).await;
}
编译错误发生在 and_then
,它非常神秘,它说的是:
error[E0599]: no method named `and_then` found for struct `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>` in the current scope
--> src\main.rs:21:14
|
21 | .and_then(user::get_users);
| ^^^^^^^^ method not found in `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>`
|
::: C:\Users\Yasmani\.cargo\registry\src\github.com-1ecc6299db9ec823\warp-0.2.3\src\filter\and.rs:12:1
|
12 | pub struct And<T, U> {
| --------------------
| |
| doesn't satisfy `_: warp::filter::FilterBase`
| doesn't satisfy `_: warp::filter::Filter`
|
= note: the method `and_then` exists but the following trait bounds were not satisfied:
`warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
`&warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `&warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
`&mut warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `&mut warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
我认为这与 ref_filter
中的闭包返回的类型不匹配函数 get_users
期望的类型有关,但我不确定为什么。我相信闭包 returns 和 Arc<RwLock<MysqlConnection>>>
和 get_users
函数是一样的。有什么问题?
问题是您的闭包的 return 类型由于某种原因未知。仔细观察编译器错误,你的闭包的 return 类型是 _
。这会导致 GET 过滤器的以下部分的 return 类型不是 Filter
,这反过来意味着 and_then()
未实现。
let get_users = warp::get()
.and(warp::path("users"))
.and(ref_filter.clone())
解决方案
注释闭包的 return 类型。
let ref_filter = warp::any().map(move || -> Arc<RwLock<MysqlConnection>> {reference_counter.clone()});
(也许你会发现db_connection
的类型不是你所期望的。)
上下文
在我看来 db_connection
的类型确实是您问题的根源。我试图通过用空结构或 impl Foo
代替 db_connection
从您的代码创建 MWE,但它编译没有任何问题。
问题是 Diesel API 中的 MysqlConnection
没有实现 Warp API 需要的某些 trait
。解决方案是在此处停止直接使用 MysqlConnection
类型,而是使用动态生成连接的 ConnectionPool
类型。 ConnectionPool
是 Diesel 包的 r2d2 特性的一部分。
现在想想,这很有道理。之前,我使用单个数据库连接来处理所有传入的 HTTP 请求。这很糟糕,因为该应用最终可能会同时在同一连接上进行多个读取操作。
所以,这是处理 HTTP 请求的函数:
type ConnectionPool = Pool<ConnectionManager<MysqlConnection>>;
type ConnectionLock = RwLock<ConnectionPool>;
type ConnectionLockArc = Arc<ConnectionLock>;
pub async fn get_users(lock: ConnectionLockArc) -> Result<impl Reply, Rejection>{
let users = storage::get_users(&lock);
let response = json(&users);
return Ok(response);
}
以下是使用 Warp API 进行设置的方式:
#[tokio::main]
async fn main() {
let pool = storage::establish_connection_pool();
let lock = RwLock::new(pool);
let reference = Arc::new(lock);
let resources = warp::any().map(move || reference.clone());
let get_users = warp::get()
.and(warp::path("users"))
.and(resources.clone())
.and_then(user::get_users);
warp::serve(get_users).run(([127, 0, 0, 1], 3030)).await;
}
我正在尝试设置一个简单的 GET
过滤器,但我无法编译它。
这是我要映射到请求的函数:
pub async fn get_users(reference_counter: Arc<RwLock<MysqlConnection>>) -> Result<impl Reply, Rejection> {
// Get users code here
}
这就是我将函数映射到 main.rs
中的 GET
请求的方式:
#[tokio::main]
async fn main() {
let db_connection = storage::establish_connection();
let lock = RwLock::new(db_connection);
let reference_counter = Arc::new(lock);
let ref_filter = warp::any().map(move || reference_counter.clone());
let get_users = warp::get()
.and(warp::path("users"))
.and(ref_filter.clone())
.and_then(user::get_users);
warp::serve(get_users).run(([127, 0, 0, 1], 3030)).await;
}
编译错误发生在 and_then
,它非常神秘,它说的是:
error[E0599]: no method named `and_then` found for struct `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>` in the current scope
--> src\main.rs:21:14
|
21 | .and_then(user::get_users);
| ^^^^^^^^ method not found in `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>`
|
::: C:\Users\Yasmani\.cargo\registry\src\github.com-1ecc6299db9ec823\warp-0.2.3\src\filter\and.rs:12:1
|
12 | pub struct And<T, U> {
| --------------------
| |
| doesn't satisfy `_: warp::filter::FilterBase`
| doesn't satisfy `_: warp::filter::Filter`
|
= note: the method `and_then` exists but the following trait bounds were not satisfied:
`warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
`&warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `&warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
`&mut warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::FilterBase`
which is required by `&mut warp::filter::and::And<warp::filter::and::And<impl warp::filter::Filter+std::marker::Copy, warp::filters::path::Exact<warp::filters::path::internal::Opaque<&str>>>, warp::filter::map::Map<impl warp::filter::Filter+std::marker::Copy, [closure@src\main.rs:17:39: 17:72 reference_counter:_]>>: warp::filter::Filter`
我认为这与 ref_filter
中的闭包返回的类型不匹配函数 get_users
期望的类型有关,但我不确定为什么。我相信闭包 returns 和 Arc<RwLock<MysqlConnection>>>
和 get_users
函数是一样的。有什么问题?
问题是您的闭包的 return 类型由于某种原因未知。仔细观察编译器错误,你的闭包的 return 类型是 _
。这会导致 GET 过滤器的以下部分的 return 类型不是 Filter
,这反过来意味着 and_then()
未实现。
let get_users = warp::get()
.and(warp::path("users"))
.and(ref_filter.clone())
解决方案
注释闭包的 return 类型。
let ref_filter = warp::any().map(move || -> Arc<RwLock<MysqlConnection>> {reference_counter.clone()});
(也许你会发现db_connection
的类型不是你所期望的。)
上下文
在我看来 db_connection
的类型确实是您问题的根源。我试图通过用空结构或 impl Foo
代替 db_connection
从您的代码创建 MWE,但它编译没有任何问题。
问题是 Diesel API 中的 MysqlConnection
没有实现 Warp API 需要的某些 trait
。解决方案是在此处停止直接使用 MysqlConnection
类型,而是使用动态生成连接的 ConnectionPool
类型。 ConnectionPool
是 Diesel 包的 r2d2 特性的一部分。
现在想想,这很有道理。之前,我使用单个数据库连接来处理所有传入的 HTTP 请求。这很糟糕,因为该应用最终可能会同时在同一连接上进行多个读取操作。
所以,这是处理 HTTP 请求的函数:
type ConnectionPool = Pool<ConnectionManager<MysqlConnection>>;
type ConnectionLock = RwLock<ConnectionPool>;
type ConnectionLockArc = Arc<ConnectionLock>;
pub async fn get_users(lock: ConnectionLockArc) -> Result<impl Reply, Rejection>{
let users = storage::get_users(&lock);
let response = json(&users);
return Ok(response);
}
以下是使用 Warp API 进行设置的方式:
#[tokio::main]
async fn main() {
let pool = storage::establish_connection_pool();
let lock = RwLock::new(pool);
let reference = Arc::new(lock);
let resources = warp::any().map(move || reference.clone());
let get_users = warp::get()
.and(warp::path("users"))
.and(resources.clone())
.and_then(user::get_users);
warp::serve(get_users).run(([127, 0, 0, 1], 3030)).await;
}