use std::net::SocketAddr;
use bytes::{Buf, Bytes, BytesMut};
use headers::{Header, HeaderMapExt};
use hyper::body::HttpBody;
use hyper::http::{
self,
header::{HeaderMap, HeaderName, HeaderValue},
};
use route_recognizer::Params;
use serde::de::DeserializeOwned;
pub type HyperRequest = hyper::Request<hyper::Body>;
use crate::errors::errors::{
invalid_header, invalid_params, missing_app_state,
missing_cookie, missing_header, missing_param,
};
use crate::{middleware::WithState, Error};
pub struct Request {
pub(crate) inner: HyperRequest,
params: Params,
remote_address: Option<SocketAddr>,
route_path: Option<String>,
}
impl Request {
pub fn new(request: HyperRequest, remote_address: Option<SocketAddr>) -> Self {
Request {
inner: request,
params: Params::new(),
remote_address,
route_path: None,
}
}
pub fn inner(&self) -> &HyperRequest {
&self.inner
}
pub fn innner_mut(&mut self) -> &mut HyperRequest {
&mut self.inner
}
pub fn headers(&self) -> &HeaderMap<HeaderValue> {
self.inner.headers()
}
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
self.inner.headers_mut()
}
pub fn method(&self) -> &http::Method {
self.inner.method()
}
pub fn uri(&self) -> &http::Uri {
self.inner.uri()
}
pub fn path(&self) -> &str {
self.uri().path()
}
pub fn version(&self) -> http::Version {
self.inner.version()
}
pub fn remote_addr(&self) -> Option<SocketAddr> {
self.remote_address
}
pub fn params(&self) -> &Params {
&self.params
}
pub fn get_cookie(&self, name: &str) -> Result<String, Error> {
let cookie: headers::Cookie = self.get_typed_header()?;
cookie
.get(name)
.ok_or_else(|| missing_cookie(name))
.map(|s| s.to_string())
}
pub fn get_state<T>(&self) -> Result<&T, Error>
where
T: Send + Sync + 'static + Clone,
{
WithState::get_state(self).ok_or_else(|| missing_app_state(std::any::type_name::<T>()))
}
pub fn get_extension<T>(&self) -> Option<&T>
where
T: Send + Sync + 'static + Clone,
{
self.inner.extensions().get::<T>()
}
pub fn get_extension_mut<T>(&mut self) -> Option<&mut T>
where
T: Send + Sync + 'static + Clone,
{
self.inner.extensions_mut().get_mut::<T>()
}
pub fn insert_extension<T>(&mut self, val: T)
where
T: Send + Sync + 'static + Clone,
{
self.inner.extensions_mut().insert(val);
}
pub fn get_param<T>(&self, param: &str) -> Result<T, Error>
where
T: std::str::FromStr,
<T as std::str::FromStr>::Err: std::error::Error,
{
match self.params.find(param) {
Some(param) => param
.parse()
.map_err(|e| invalid_params(e, param, std::any::type_name::<T>())),
None => Err(missing_param(param)),
}
}
pub fn get_header<K>(&self, header: K) -> Result<&HeaderValue, Error>
where
HeaderName: From<K>,
{
let key: HeaderName = header.into();
let key_cloned = key.clone();
let value = self
.inner
.headers()
.get(key)
.ok_or_else(|| missing_header(key_cloned))?;
Ok(value)
}
pub fn get_typed_header<T: Header + Send + 'static>(&self) -> Result<T, Error> {
self.inner
.headers()
.typed_get::<T>()
.ok_or_else(|| invalid_header(T::name().as_str()))
}
pub fn get_query<T: DeserializeOwned + Default>(&self) -> Result<T, Error> {
match self.inner.uri().query() {
Some(query) => serde_urlencoded::from_str(query).map_err(Error::from),
None => Ok(Default::default()),
}
}
pub async fn read_body(&mut self) -> Result<Bytes, Error> {
let mut bufs = BytesMut::new();
while let Some(buf) = self.inner.body_mut().data().await {
let buf = buf?;
if buf.has_remaining() {
bufs.extend(buf);
}
}
Ok(bufs.freeze())
}
pub async fn read_form<T: DeserializeOwned>(&mut self) -> Result<T, Error> {
let body = self.read_body().await?;
let form = serde_urlencoded::from_bytes(&body)?;
Ok(form)
}
pub async fn read_json<T: DeserializeOwned>(&mut self) -> Result<T, Error> {
let body = self.read_body().await?;
let json = serde_json::from_slice(&body)?;
Ok(json)
}
pub(crate) fn route_path(&self) -> &str {
match self.route_path {
Some(ref path) => path,
None => self.inner.uri().path(),
}
}
pub(crate) fn set_route_path(&mut self, path: &str) {
self.route_path = Some(path.to_string());
}
pub(crate) fn merge_params(&mut self, other: &Params) -> &Params {
for (k, v) in other {
self.params.insert(k.to_string(), v.to_string());
}
&self.params
}
}
impl From<hyper::Request<hyper::Body>> for Request {
fn from(req: hyper::Request<hyper::Body>) -> Self {
Request::new(req, None)
}
}