use actix_web::{FromRequest, HttpRequest, dev::Payload};
use serde::de::DeserializeOwned;
use std::future::{ready, Ready};
#[derive(Debug)]
pub struct Path<T>(pub T);
impl<T: DeserializeOwned + 'static> FromRequest for Path<T> {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
let mut map = serde_json::Map::new();
for (key, value) in req.match_info().iter() {
map.insert(key.to_string(), serde_json::json!(value));
}
match T::deserialize(serde_json::Value::Object(map)) {
Ok(data) => ready(Ok(Path(data))),
Err(e) => ready(Err(actix_web::error::ErrorBadRequest(e))),
}
}
}
#[derive(Debug)]
pub struct Query<T>(pub T);
impl<T: DeserializeOwned + 'static> FromRequest for Query<T> {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
match serde_urlencoded::from_str::<T>(req.query_string()) {
Ok(data) => ready(Ok(Query(data))),
Err(e) => ready(Err(actix_web::error::ErrorBadRequest(e))),
}
}
}
#[derive(Debug, Clone)]
pub struct State<T>(pub T);
impl<T: Clone + Send + Sync + 'static> FromRequest for State<T> {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
ready(
req.app_data::<actix_web::web::Data<T>>()
.map(|data| State(data.as_ref().clone()))
.ok_or_else(|| actix_web::error::ErrorInternalServerError("State not found"))
)
}
}