2

我正在尝试设置一个简单的GET过滤器,但我无法编译它。

这是我试图映射到请求的函数:

pub async fn get_users(reference_counter: Arc<RwLock<MysqlConnection>>) -> Result<impl Reply, Rejection> {
   // Get users code here
}

这就是我将函数映射到GET请求的方式main.rs

#[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,但我不知道为什么。我相信闭包返回 anArc<RwLock<MysqlConnection>>>并且get_users函数采用相同的方法。问题是什么?

4

2 回答 2

2

问题是您的闭包的返回类型由于某种原因是未知的。仔细查看编译器错误,您的闭包的返回类型是_. 这会导致 GET 过滤器的以下部分的返回类型不是Filter,这反过来意味着and_then()未实现。

let get_users = warp::get()
        .and(warp::path("users"))
        .and(ref_filter.clone())

解决方案

注释闭包的返回类型。

let ref_filter = warp::any().map(move || -> Arc<RwLock<MysqlConnection>> {reference_counter.clone()});

(也许你会发现类型db_connection不是你所期望的。)

语境

在我看来,类型db_connection确实是您问题的根源。我尝试通过替换空结构或impl Foofor 来从您的代码创建 MWE db_connection,但它编译时没有任何问题。

于 2020-06-18T16:23:08.937 回答
1

问题在于MysqlConnectionDiesel API 没有实现traitWarp API 所需的一些功能。解决方案是在此处直接停止使用该MysqlConnection类型,而使用ConnectionPool动态生成连接的 a 。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;
 }
于 2020-06-19T00:20:02.147 回答