rust - 通过 FromRequest 传递数据库引用
问题描述
我在 Rust 中使用 Rocket Web 框架,并且我有一个数据库池(DbConn)。
#[database("redirect-api")]
pub struct DbConn(diesel::PgConnection);
我已经能够将 DbConn 传递给每条路由,但是在尝试将它传递给 from_request 调用的函数时遇到了麻烦。在 get_redirects 中,我使用了 ApiKey 结构,我如何理解它,FromRequest 是一个检查输入的守卫。在 from_request 中,我调用了 is_valid 函数,但不能将其传递给 DbConn,就像我从路由调用 is_valid 一样,比如直接从 get_redirects 调用。
我希望能够在 is_valid 函数中使用 DbConn,但是如果我尝试使用 &DbConn,则会收到此错误
the trait `diesel::Connection` is not implemented for `fn(PooledConnection<<diesel::PgConnection as Poolable>::Manager>) -> DbConn {DbConn}`
|
43 | .load::<Token>(&DbConn)
| ^^^^^^^ the trait `diesel::Connection` is not implemented for `fn(PooledConnection<<diesel::PgConnection as Poolable>::Manager>) -> DbConn {DbConn}`
|
= note: required because of the requirements on the impl of `LoadQuery<fn(PooledConnection<<diesel::PgConnection as Poolable>::Manager>) -> DbConn {DbConn}, models::Token>` for `diesel::query_builder::SelectStatement<schema::tokens::table, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<schema::tokens::columns::token, diesel::expression::bound::Bound<diesel::sql_types::Text, std::string::String>>>, query_builder::order_clause::NoOrderClause, query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<BigInt, i64>>>`
#![feature(decl_macro)]
use rocket::{catchers, routes};
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate rocket_contrib;
use diesel::prelude::*;
// --snip--
#[database("redirect-api")]
pub struct DbConn(diesel::PgConnection);
// --snip--
fn is_valid(key: &str) {
// ... use key, hash is, etc
// check if hash is in database
// this function needs the database pool or DbConn
// but it can't be passed through FromRequest
}
impl<'a, 'r> FromRequest<'a, 'r> for ApiKey {
type Error = ApiKeyError;
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let keys: Vec<_> = request.headers().get("x-api-key").collect();
match keys.len() {
0 => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
1 if is_valid(keys[0]) => Outcome::Success(ApiKey(keys[0].to_string())),
1 => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
_ => Outcome::Failure((Status::BadRequest, ApiKeyError::BadCount)),
}
}
}
// --snip--
#[get("/redirects")]
pub fn get_redirects(_key: ApiKey, conn: DbConn) -> String {
// ... do database things with conn
format!("something {}", some_value_from_db)
}
// --snip--
fn main() {
rocket::ignite()
.register(catchers![not_found])
.attach(DbConn::fairing())
.mount("/", routes![root, get_redirect])
.launch();
}
解决方案
推荐阅读
- mongodb - 用于查找与特定数组键值匹配的字段的 Mongo 查询
- node.js - AWS ALB 后面 EC2 中 Docker 上 NodeJS 的客户端超时
- android - 在arcore中绘制垂直线到相机中心
- matlab - 自动插入nans而不覆盖
- java - Calendar.setTimeInMillis 错误 - 为什么会这样?
- c - 了解结构中的填充
- python - 我该怎么做才能使此代码正常工作?(Python)
- javascript - 如何使用元素数据属性最小化功能重复?
- wordpress - 如何按自定义字段过滤 ACF 帖子对象字段/搜索?
- xamarin.forms - Xamarin(Forms 或 Native)和带有 DRM(ProtectionInfo)的播放器