Skip to content

Commit

Permalink
Merge pull request #33 from meilisearch/actix-web/query-parameter
Browse files Browse the repository at this point in the history
Provide an extractor for the query parameters in actix-web
  • Loading branch information
irevoire authored Feb 14, 2023
2 parents 577197b + d4c9c00 commit 9a792fa
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 1 deletion.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ actix-web = { version = "4.3.0", optional = true }
futures = { version = "0.3.25", optional = true }
deserr-internal = { version = "=0.4.0", path = "derive" }
strsim = "0.10.0"
actix-http = { version = "3.3.0", optional = true }
actix-utils = { version = "3.0.1", optional = true }
serde_urlencoded = "0.7.1"

[features]
default = ["serde-json", "serde-cs", "actix-web"]
serde-json = ["serde_json"]
serde-cs = ["dep:serde-cs"]
actix-web = ["dep:actix-web", "futures"]
actix-web = ["dep:actix-web", "futures", "actix-http", "actix-utils"]

[dev-dependencies]
automod = "1.0"
Expand Down
4 changes: 4 additions & 0 deletions src/actix_web/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#[cfg(feature = "serde-json")]
mod query_parameters;
#[cfg(feature = "serde-json")]
mod serde_json;

#[cfg(feature = "serde-json")]
pub use self::query_parameters::AwebQueryParameter;
#[cfg(feature = "serde-json")]
pub use self::serde_json::{AwebJson, AwebJsonExtractFut};
71 changes: 71 additions & 0 deletions src/actix_web/query_parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//! A module to parse query parameter as String with deserr

use std::marker::PhantomData;
use std::{fmt, ops};

use crate::{DeserializeError, Deserr};
use actix_http::Payload;
use actix_utils::future::{err, ok, Ready};
use actix_web::web::Query;
use actix_web::{FromRequest, HttpRequest, ResponseError};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct AwebQueryParameter<T, E>(pub T, PhantomData<*const E>);

impl<T, E> AwebQueryParameter<T, E> {
/// Unwrap into inner `T` value.
pub fn into_inner(self) -> T {
self.0
}
}

impl<T, E> AwebQueryParameter<T, E>
where
T: Deserr<E>,
E: DeserializeError + ResponseError + 'static,
{
pub fn from_query(query_str: &str) -> Result<Self, actix_web::Error> {
let value = Query::<serde_json::Value>::from_query(query_str)?;

match deserr::deserialize::<_, _, E>(value.0) {
Ok(data) => Ok(AwebQueryParameter(data, PhantomData)),
Err(e) => Err(e)?,
}
}
}

impl<T, E> ops::Deref for AwebQueryParameter<T, E> {
type Target = T;

fn deref(&self) -> &T {
&self.0
}
}

impl<T, E> ops::DerefMut for AwebQueryParameter<T, E> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}

impl<T: fmt::Display, E> fmt::Display for AwebQueryParameter<T, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl<T, E> FromRequest for AwebQueryParameter<T, E>
where
T: Deserr<E>,
E: DeserializeError + ResponseError + 'static,
{
type Error = actix_web::Error;
type Future = Ready<Result<Self, actix_web::Error>>;

#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
AwebQueryParameter::from_query(req.query_string())
.map(ok)
.unwrap_or_else(err)
}
}
1 change: 1 addition & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ impl Sequence for Infallible {
unreachable!()
}
}

impl Map for Infallible {
type Value = Self;
type Iter = std::iter::Empty<(String, Infallible)>;
Expand Down

0 comments on commit 9a792fa

Please sign in to comment.