use contrib::Json;
#[cfg(feature = "unstable")]
use contrib::MultiPartMap;
use http::request::Parts;
use hyper::{
header::{HeaderMap, HeaderValue},
Body,
Method,
Uri,
Version,
};
use percent_encoding::percent_decode;
use routing::recognizer::Params;
use serde::de::DeserializeOwned;
use serde_json::{self, from_slice};
use serde_qs::{self, from_str};
#[cfg(feature = "unstable")]
use std::collections::HashMap;
use std::net::SocketAddr;
#[derive(Debug)]
pub struct Request {
pub(crate) parts: Parts,
pub(crate) body: Body,
pub(crate) remote: Option<SocketAddr>,
}
#[derive(Debug)]
pub enum JsonError {
None,
Err(serde_json::Error),
}
#[derive(Debug)]
pub enum QueryParseError {
Err(serde_qs::Error),
None,
}
impl Request {
pub(crate) fn new(parts: Parts, body: Body) -> Self {
Self {
parts,
body,
remote: None,
}
}
#[inline]
pub fn version(&self) -> &Version {
&self.parts.version
}
#[inline]
pub fn headers(&self) -> &HeaderMap<HeaderValue> {
&self.parts.headers
}
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
&mut self.parts.headers
}
#[inline]
pub fn method(&self) -> &Method {
&self.parts.method
}
#[inline]
pub fn uri(&self) -> &Uri {
&self.parts.uri
}
#[inline]
pub fn path(&self) -> &str {
self.parts.uri.path()
}
#[inline]
pub fn remote_ip(&self) -> Option<SocketAddr> {
self.remote
}
#[inline]
pub fn query<T>(&self) -> Result<T, QueryParseError>
where
T: DeserializeOwned,
{
self.uri()
.query()
.ok_or(QueryParseError::None)
.and_then(|encoded| Ok(percent_decode(encoded.as_bytes()).decode_utf8_lossy()))
.and_then(|query| from_str::<T>(&query).map_err(QueryParseError::Err))
}
pub fn params(&self) -> Option<&Params> {
self.parts.extensions.get::<Params>()
}
pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
self.parts.extensions.get::<T>()
}
pub fn set<T: Send + Sync + 'static>(&mut self, value: T) -> Option<T> {
self.parts.extensions.insert::<T>(value)
}
pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
self.parts.extensions.remove::<T>()
}
#[inline]
pub fn body(&mut self) -> Body {
::std::mem::replace(&mut self.body, Body::empty())
}
pub fn json<T>(&self) -> Result<T, JsonError>
where
T: DeserializeOwned,
{
match self.get::<Json>() {
Some(ref slice) => from_slice::<T>(slice).map_err(JsonError::Err),
_ => Err(JsonError::None),
}
}
#[cfg(feature = "unstable")]
pub fn form(&self) -> Result<HashMap<String, String>, JsonError> {
match self.get::<MultiPartMap>() {
Some(ref map) => Ok(map.0.clone()),
_ => Err(JsonError::None),
}
}
#[inline]
pub fn body_ref(&self) -> &Body {
&self.body
}
#[inline]
pub fn body_mut(&mut self) -> &mut Body {
&mut self.body
}
pub fn set_body(&mut self, body: Body) {
self.body = body
}
}