我正在用 Rust 和 Warp 构建一个 graphql api。我已经浏览了文档,但我仍然没有弄清楚如何链接过滤器,尤其是检查authorization
请求标头时。
let context_extractor = warp::any()
// this code rejects all request which doesn't contain the authorization in header
// I'd like to make to check if authorization in header
.and(warp::header::<String>("authorization"))
.map(|token: String| -> Context {
let token_data = match verify_jwt(token) {
Ok(t) => t,
Err(_) => return Context { user_id: 0 },
};
Context {
user_id: token_data.claims.user_id,
}
});
let handle_request = move |context: Context,
request: juniper::http::GraphQLRequest|
-> Result<Vec<u8>, serde_json::Error> {
serde_json::to_vec(&request.execute(&schema, …
Run Code Online (Sandbox Code Playgroud) 我想使用warp提供多个连接,以便我可以将每个 http 请求重定向到 https。这就是我现在要做的事情。
#[tokio::main]
async fn main() {
let http_routes = warp::path("http").map(|| {
println!("This is http server");
warp::redirect(Uri::from_static("https://127.0.0.1:2443"))
});
let https_routes = warp::any().map(|| {
println!("This is https server");
"Hello, World! You are connected through tls connection."
});
let _http_warp = warp::serve(http_routes)
.run(([127, 0, 0, 1], 2080)).await;
let _https_warp = warp::serve(https_routes)
.tls()
.cert_path("sec/dmp.cert")
.key_path("sec/dmp.key")
.run(([127, 0, 0, 1], 2443)).await;
}
Run Code Online (Sandbox Code Playgroud)
这不能按预期工作。它只侦听端口 2080,而不侦听 2443
我也尝试过 future::join
#[tokio::main]
async fn main() {
----snip----
let (_http_addr, http_warp) = warp::serve(http_routes)
.bind_ephemeral(([127, 0, …
Run Code Online (Sandbox Code Playgroud) 我定义了一个路由和一个端点函数。我还注入了一些依赖项。
pub fn route1() -> BoxedFilter<(String, ParamType)> {
warp::get()
.and(warp::path::param())
.and(warp::filters::query::query())
.and(warp::path::end())
.boxed()
}
pub async fn handler1(
query: String,
param: ParamType,
dependency: DependencyType,
) -> Result<impl warp::Reply, warp::Rejection> {
}
Run Code Online (Sandbox Code Playgroud)
let api = api::routes::route1()
.and(warp::any().map(move || dependency))
.and_then(api::hanlders::hander1);
Run Code Online (Sandbox Code Playgroud)
这一切似乎工作正常。
但是,我希望能够在多个端点前面放置一些东西,以检查查询参数中的有效键。在里面handler1
我可以添加:
if !param.key_valid {
return Ok(warp::reply::with_status(
warp::reply::json(&""),
StatusCode::BAD_REQUEST,
));
}
Run Code Online (Sandbox Code Playgroud)
我不想将它单独添加到每个处理程序中。
似乎我应该能够通过 来做到这一点filter
,但我无法弄清楚。我试过使用.map()
但随后返回多个项目将其转换为一个元组,我必须更改我的下游函数签名。理想情况下,我想找到一种方法来添加验证或其他过滤器,这些过滤器可以在没有任何下游值了解它们的情况下拒绝请求。
使用warp.rs 0.2.2,让我们考虑一个基本的 Web 服务,它有一个路由GET /
:
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let getRoot = warp::get().and(warp::path::end()).and_then(routes::getRoot);
warp::serve(getRoot).run(([0, 0, 0, 0], 3030)).await;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
我的目标是?
在路由处理程序中用于错误处理,所以让我们编写一个可以错误并在早期返回的程序crate::routes
:
use crate::errors::ServiceError;
use url::Url;
pub async fn getRoot() -> Result<impl warp::Reply, warp::Rejection> {
let _parsed_url = Url::parse(&"https://whydoesn.it/work?").map_err(ServiceError::from)?;
Ok("Hello world !")
}
Run Code Online (Sandbox Code Playgroud)
这个版本有效。这里返回的错误Url::parse()
是url::ParseError
为了在错误类型之间转换,从url::ParseError
到ServiceError
,然后从ServiceError
到warp::Rejection
,我写了一些错误助手crate::errors
:
#[derive(thiserror::Error, Debug)]
pub enum ServiceError {
#[error(transparent)]
Other(#[from] anyhow::Error), // source …
Run Code Online (Sandbox Code Playgroud) 在启用跟踪的情况下使用warp时,我发现跟踪输出很嘈杂。这是因为在每个请求上尝试的每个路由(即过滤器)都会发出一组跟踪事件。
因此,如果我有以下路线,请遵循 warp repo 中的跟踪示例:
let routes = hello
.or(goodbye)
.with(warp::trace::request());
Run Code Online (Sandbox Code Playgroud)
每次goodbye
收到对路由的请求时,都会发出两组跟踪事件:一组用于 hello 路由,导致 404 拒绝,另一组用于再见路由,应该回复。
有没有人对如何设置路由以消除为 404 拒绝发出的所有跟踪提供建议,并且只为回复的路由发出跟踪?
我有一个 Rust 应用程序,使用warp
. 它实现了 RESTful CRUD API。我需要每个路由处理程序(即最终由扭曲过滤器调用的函数)能够访问并(在大多数情况下)改变共享应用程序状态。
我可以编译它的唯一方法是Arc<Mutex<State>>
为每个路由克隆一个:
/* internal_state is loaded from a dump file earlier on and is of type `State` */
let state: Arc<Mutex<State>> = Arc::new(Mutex::new(internal_state));
let index_book_state: Arc<Mutex<State>> = state.clone();
let create_book_state: Arc<Mutex<State>> = state.clone();
let read_book_state: Arc<Mutex<State>> = state.clone();
let create_order_state: Arc<Mutex<State>> = state.clone();
let read_order_state: Arc<Mutex<State>> = state.clone();
let update_order_state: Arc<Mutex<State>> = state.clone();
let destroy_order_state: Arc<Mutex<State>> = state.clone();
/* define CRUD routes for order books */
let book_prefix = …
Run Code Online (Sandbox Code Playgroud) 我正在使用warp
库在 Rust 中制作一个网络应用程序。我正在尝试提供静态文件。\n我已从Doc阅读了其文档。
这是我的代码片段
\n\nuse serde::Deserialize;\nuse serde::Serialize;\nuse warp::path;\nuse warp::Filter;\n\n#[tokio::main]\nasync fn main() {\n let static_assets = warp::path("static").and(warp::fs::dir("/www/static"));\n\n // let routes = get_routes.or(post_routes).or(static_assets).or(file_route);\n let routes = static_assets;\n\n warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n但是当我访问该路径时localhost:3030/static/index.js
,它会返回404
响应
这是文件树
\n\nsrc\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.rs\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 www\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 static\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 index.js\n
Run Code Online (Sandbox Code Playgroud)\n 如何将依赖项注入 Warp 中的路由处理程序?一个简单的例子如下。我有一个路由,我想提供一个在启动时确定的静态值,但过滤器将值传递给最终处理程序。如何在不创建全局变量的情况下传递额外数据?这对于依赖注入很有用。
pub fn root_route() -> BoxedFilter<()> {
warp::get().and(warp::path::end()).boxed()
}
pub async fn root_handler(git_sha: String) -> Result<impl warp::Reply, warp::Rejection> {
Ok(warp::reply::json(
json!({
"sha": git_sha
})
.as_object()
.unwrap(),
))
}
#[tokio::main]
async fn main() {
let git_sha = "1234567890".to_string();
let api = root_route().and_then(root_handler);
warp::serve(api).run(([0,0,0,0], 8080)).await;
}
Run Code Online (Sandbox Code Playgroud) 一个 Rust 新手,尝试通过结合来编写一个 Web 服务
https://github.com/seanmonstar/warp/blob/master/examples/todos.rs和https://github.com/launchbadge/sqlx/blob/master/examples/postgres/todos/src/main.rs
以下代码处于运行状态。我的问题是,我是否需要为每个处理程序克隆 dbpool?Rust 中的惯用方式是什么(我来自 Java/Kotlin->Go 背景,FWIW)
#![deny(warnings)]
use sqlx::postgres::{PgPoolOptions};
use std::env;
use warp::Filter;
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://:@localhost/todo_db").await?;
if env::var_os("RUST_LOG").is_none() {
env::set_var("RUST_LOG", "todos=info");
}
pretty_env_logger::init();
let api = filters::todos(pool);
let routes = api.with(warp::log("todos"));
// Start up the server...
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
Ok(())
}
mod filters {
use sqlx::{Pool, Postgres};
use super::handlers;
use super::models::{ListOptions, Todo};
use warp::Filter;
pub fn todos(
db: Pool<Postgres>,
) …
Run Code Online (Sandbox Code Playgroud) 我正在尝试在 warp 中记录请求/响应主体。
使用时warp::log::custom
,该Info
结构不包含任何有关它的信息。
当尝试实现我自己的日志包装器时,基于 的实现warp::log
,该Route
结构是私有的(除其他外)。
我可以使用反序列化后记录主体
warp::body::json().map(|it| {
println!("Hello : {:?}", it);
it
})
Run Code Online (Sandbox Code Playgroud)
但如果用户没有发送正确的正文,它将无法工作。此外,我正在寻找一种简单的方法来记录所有请求主体。