use crate::{
store::{self, LazyReqStore},
Builder, Request,
};
use futures::future;
use serde::Deserialize;
use warp::{filters, reject, Filter, Rejection};
pub fn json_rpc() -> impl Filter<Extract = (Builder,), Error = Rejection> + Copy {
filters::method::post()
.and(filters::header::exact("Content-Type", "application/json"))
.and(store::filled().or(store_req()))
.map(|_| ())
.untuple_one()
.and(store::stored_req().map(|req: Request| Builder::new(req.id())))
}
fn store_req() -> impl Filter<Extract = (), Error = Rejection> + Copy {
filters::body::json::<Request>()
.and(store::store())
.map(|req: Request, store: LazyReqStore| {
store
.fill(req)
.expect("LazyReqStore is filled more than twice");
})
.untuple_one()
}
pub fn method(name: &'static str) -> impl Filter<Extract = (), Error = Rejection> + Copy {
store::stored_req()
.and_then(move |req: Request| {
if req.method() == name {
log::info!(target: "warp_json_rpc", "\"{}\" RPC", name);
future::ok(())
} else {
future::err(reject::reject())
}
})
.untuple_one()
}
pub fn params<T>() -> impl Filter<Extract = (T,), Error = Rejection> + Copy
where
for<'de> T: Deserialize<'de> + Send,
{
store::stored_req().and_then(|req: Request| {
future::ready(req.deserialize_param::<T>().map_err(|_| reject::reject()))
})
}