warp
warp copied to clipboard
Can't have a function returning a `Wrap`
Version 0.3.2
Platform Linux sufjan 5.15.0-46-generic #49~20.04.1-Ubuntu SMP Thu Aug 4 19:15:44 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Description
Thanks to the wrap_fn function, warp users are able to create their own Wraps for use with .with(). Super cool! However, in order to have a nice reusable Wrap, I would like to have a function that returns a Wrap. We can do something similar with filters by making a function that returns impl Filter<...>. However, this doesn't work with Wrap because Wrap, WrapSealed, and the concrete type WrapFn are all private, so afaict there's no way for me to define a function that returns the result of wrap_fn.
Here's the (pseudo)code that I want to write:
// auth.rs
fn basic<F: Filter>(user: String, pass: String) -> impl Wrap<F> {
wrap_fn(|filter: F| {
...
})
}
I would also be happy to put the concrete type WrapFn<???> as the return type instead. However, instead I had to write the following code:
#[macro_export]
macro_rules! basic {
($user:expr, $pass:expr) => {{
use tap::Pipe;
let credentials =
Some("Basic ".to_string() + &base64::encode(format!("{}:{}", $user, $pass)));
let check_creds = move |auth: Option<String>| {
if auth == credentials {
Ok(())
} else {
Err(reject::custom($crate::auth::AuthorizationRequired))
}
.pipe(|ret| async { ret })
};
wrap_fn(move |filter| {
header::optional("authorization")
.and_then(check_creds.clone())
.and(filter)
.map(|(), res| res)
.recover(|rej: Rejection| async {
if let Some($crate::auth::AuthorizationRequired) = rej.find() {
Ok(hyper::Response::builder()
.status(401)
.header("WWW-Authenticate", "Basic")
.body("")
.unwrap())
} else {
Err(rej)
}
})
})
}};
}
This shouldn't be a macro, but I couldn't make it a function, so this was the next best way to make my wrapper reusable. I also noticed that the Wrap trait is marked as pub, but it's in the private module warp::filter::wrap and isn't re-exported anywhere, so it's inaccessible to the user. Did you mean to re-export Wrap so that it can be used like Filter?
Today I tried to do something similar as well. I was attempting to make my own CORS wrapper using WrapFn as the built-in one didn't fit my needs very well. I ended up just passing in a function and handling it differently.