poem_queryext/
query_ext.rs

1use poem::{http::StatusCode, Error, FromRequest, Result};
2use serde::Deserialize;
3use std::marker::PhantomData;
4use urlencoding::decode;
5
6/// Deserialize struct wrapper.
7#[derive(Debug)]
8pub struct QueryExt<'a, T>(pub T, PhantomData<&'a T>)
9where
10    T: Deserialize<'a>;
11
12impl<'a, T> FromRequest<'a> for QueryExt<'a, T>
13where
14    T: Deserialize<'a>,
15{
16    async fn from_request(req: &'a poem::Request, _: &mut poem::RequestBody) -> Result<Self> {
17        let path_and_query = req.uri().path_and_query();
18        if let Some(path_and_query) = path_and_query {
19            let path_and_query = path_and_query.as_str().split_once("?");
20            let query = match path_and_query {
21                Some((_, query)) => query,
22                None => "",
23            };
24            let decode_query = match decode(query) {
25                Ok(query) => query.into_owned(),
26                Err(err) => {
27                    return Err(Error::from_string(
28                        format!("decode query string error:{}", err.to_string()),
29                        StatusCode::INTERNAL_SERVER_ERROR,
30                    ));
31                }
32            };
33            //leak the decode_query
34            let decode_query = Box::leak(decode_query.into_boxed_str());
35            //parse query string to object
36            let object = serde_qs::from_str::<T>(decode_query);
37            match object {
38                Ok(object) => {
39                    return Ok(QueryExt(object, PhantomData));
40                }
41                Err(err) => {
42                    return Err(Error::from_string(
43                        format!("parse query string to object error:{}", err.to_string()),
44                        StatusCode::INTERNAL_SERVER_ERROR,
45                    ));
46                }
47            }
48        } else {
49            return Err(Error::from_status(StatusCode::INTERNAL_SERVER_ERROR));
50        }
51    }
52}