warp
warp copied to clipboard
allow injecting a constant into a route
I have a object which needs to be used by all handlers. I'm not sure how to "share" this reference without recreating / singltoning it.
Toy example here:
struct Server {
something_expensive: ExpensiveThing
}
impl Server {
fn do_something(&self) -> i32 { return 1}
}
fn main() {
let server = Server::defaultI();
// how do I pass this server into the "then" closure?
warp::path("expensive").and(warp::body::json()).then(|request: Context| async move {
let x = server.do_something(request); // this is an error:
warp::reply::json(&x)
});
}
---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this closure implements `FnOnce`, not `Fn`
| |
| the requirement to implement `Fn` derives from here
What I want:
2 options:
- use the struct function as a handler in "
and
" chain (but didn't work :( ) - pass the server into the closure as an "injected" argument i.e.
warp::path("expensive").and(warp::body::json()).then(|request: Context, server: Server <<<< This is passed along| async move {
server.do_something()
}
perhaps something like this exists but can't find it in documentation:
let server = Server::default();
warp::path("expensive").inject(server).and(warp::body::json()).then(|request: Context, server: Server| async move {
Besides, maybe we can define a new filter named constant
or similar that injects constants in the and
chain:
pub fn constant<T: Clone + Send>(value: T) -> impl Filter<Extract = (T,)> + Copy;
warp::path!("path")
.and(constant(server))
.and(warp::body::json())
.then(|server: Server, request: Context| { /* ... */ })
Hi, have you seen the todos example and how the database is inserted?
Hi , I didn't notice that example but in any case it gets cloned each time right?
fn with_db(db: Db) -> impl Filter<Extract = (Db,), Error = std::convert::Infallible> + Clone {
warp::any().map(move || db.clone())
}
I didn't notice that example but in any case it gets cloned each time right?
It does, kind of. But the thing getting cloned is only an Arc<Something>
, where Something can be your potentially expensive object. This way, the reference count will be increased and decreased for each matched route (so better put the thing after the actual url matching), but the object itself does not need to be cloned.