use http_types::response::Builder as ResponseBuilder;
use http_types::request::Parts as ReqParts;
use utils::RequestAddonCollection;
pub use http_types::Extensions;
pub use hyper::Method;
pub use hyper::Uri;
pub use hyper::Version;
pub use hyper::Body;
pub use hyper::body::Payload;
pub use hyper::StatusCode;
pub use hyper::Request;
pub use hyper::Response;
/// Headers types re-export
pub mod header {
pub use http_types::header::*;
pub use hyperx::mime;
pub use hyperx::header::*;
}
use futures::Future;
use futures::Stream;
use http_types::HttpTryFrom;
use std::any::Any;
static EMPTY_BODY: &[u8] = b"";
/// A Structure which represent an http request with a fully loaded body
#[derive(Debug)]
pub struct SyncRequest {
/// Method
head: ReqParts,
/// Body
body: Vec<u8>,
/// Request Params
addons: RequestAddonCollection,
current_path: String,
captures: Vec<String>,
}
impl SyncRequest {
/// Construct a new Request.
#[inline]
pub fn new(head: ReqParts,
body: Vec<u8>,
) -> SyncRequest {
let cp = head.uri.path().to_owned();
SyncRequest {
head,
body,
addons: RequestAddonCollection::new(),
current_path: cp,
captures: Vec::new(),
}
}
/// Returns a reference to the associated HTTP method.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<()> = Request::default();
/// assert_eq!(*request.method(), Method::GET);
/// ```
#[inline]
pub fn method(&self) -> &Method {
&self.head.method
}
/// Returns a mutable reference to the associated HTTP method.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<()> = Request::default();
/// *request.method_mut() = Method::PUT;
/// assert_eq!(*request.method(), Method::PUT);
/// ```
#[inline]
pub fn method_mut(&mut self) -> &mut Method {
&mut self.head.method
}
/// Returns a reference to the associated URI.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<()> = Request::default();
/// assert_eq!(*request.uri(), *"/");
/// ```
#[inline]
pub fn uri(&self) -> &Uri {
&self.head.uri
}
/// Returns a mutable reference to the associated URI.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<()> = Request::default();
/// *request.uri_mut() = "/hello".parse().unwrap();
/// assert_eq!(*request.uri(), *"/hello");
/// ```
#[inline]
pub fn uri_mut(&mut self) -> &mut Uri {
&mut self.head.uri
}
///
pub(crate) fn current_path_match(&mut self, re: &::regex::Regex) -> bool {
let current = self.current_path.clone();
re.find(¤t).map_or_else(|| false, |ma| {
let mut path = self.current_path.split_off(ma.end());
if path.len() < 1 {
path.push('/');
}
self.current_path = path;
true
})
}
///
pub(crate) fn current_path_match_and_capture(&mut self, re: &::regex::Regex) -> bool {
let current = self.current_path.clone();
re.captures(¤t).map_or_else(|| false, |cap| {
if let Some(ma) = cap.get(0) {
let mut path = self.current_path.split_off(ma.end());
if path.len() < 1 {
path.push('/');
}
self.current_path = path;
}
for i in 1..cap.len() {
if let Some(ma) = cap.get(i) {
self.captures.push(ma.as_str().to_owned())
}
}
true
})
}
///
pub fn captures(&self) -> &Vec<String> {
&self.captures
}
/// Returns the associated version.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<()> = Request::default();
/// assert_eq!(request.version(), Version::HTTP_11);
/// ```
#[inline]
pub fn version(&self) -> Version {
self.head.version
}
/// Returns a mutable reference to the associated version.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<()> = Request::default();
/// *request.version_mut() = Version::HTTP_2;
/// assert_eq!(request.version(), Version::HTTP_2);
/// ```
#[inline]
pub fn version_mut(&mut self) -> &mut Version {
&mut self.head.version
}
/// Returns a reference to the associated header field map.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<()> = Request::default();
/// assert!(request.headers().is_empty());
/// ```
#[inline]
pub fn headers_map(&self) -> &header::HeaderMap<header::HeaderValue> {
&self.head.headers
}
/// Returns a mutable reference to the associated header field map.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<()> = Request::default();
/// request.headers_mut().insert(HOST, HeaderValue::from_static("world"));
/// assert!(!request.headers().is_empty());
/// ```
#[inline]
pub fn headers_map_mut(&mut self) -> &mut header::HeaderMap<header::HeaderValue> {
&mut self.head.headers
}
/// Clone the HeaderMap and convert it to a more dev-friendly Headers struct
///
pub fn parsed_header(&self) -> header::Headers {
self.head.headers.clone().into()
}
/// Insert a dev-friendly Headers to the HeaderMap
///
pub fn insert_parsed_headers(&mut self, headers: header::Headers) {
let map: header::HeaderMap = headers.into();
for header in map {
if let (Some(name), value) = header {
self.head.headers.insert(name, value);
}
}
}
/// Returns a reference to the associated extensions.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<()> = Request::default();
/// assert!(request.extensions().get::<i32>().is_none());
/// ```
#[inline]
pub fn extensions(&self) -> &Extensions {
&self.head.extensions
}
/// Returns a mutable reference to the associated extensions.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<()> = Request::default();
/// request.extensions_mut().insert("hello");
/// assert_eq!(request.extensions().get(), Some(&"hello"));
/// ```
#[inline]
pub fn extensions_mut(&mut self) -> &mut Extensions {
&mut self.head.extensions
}
/// Returns a reference to the associated HTTP body.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let request: Request<String> = Request::default();
/// assert!(request.body().is_empty());
/// ```
#[inline]
pub fn body(&self) -> &Vec<u8> {
&self.body
}
/// Returns a mutable reference to the associated HTTP body.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
/// let mut request: Request<String> = Request::default();
/// request.body_mut().push_str("hello world");
/// assert!(!request.body().is_empty());
/// ```
#[inline]
pub fn body_mut(&mut self) -> &mut Vec<u8> {
&mut self.body
}
/// Returns a reference to the request add-ons
#[inline]
pub fn addons(&self) -> &RequestAddonCollection {
&self.addons
}
/// Returns a reference to the request add-ons
#[inline]
pub fn addons_mut(&mut self) -> &mut RequestAddonCollection {
&mut self.addons
}
}
/// A trait allowing the implicit conversion of a Hyper::Request into a SyncRequest
pub trait LoadBody {
///
fn load_body(self) -> Box<Future<Item=SyncRequest, Error=::hyper::Error> + Send>;
}
impl LoadBody for Request<Body> {
fn load_body(self) -> Box<Future<Item=SyncRequest, Error=::hyper::Error> + Send> {
let (parts, body) = self.into_parts();
Box::new(body.concat2().map(move |b| {
let body_vec: Vec<u8> = b.to_vec();
SyncRequest::new(parts, body_vec)
}))
}
}
/// A Structure which represent a fully mutable http response
pub struct SyncResponse {
builder: ResponseBuilder,
body: Box<ToBody>,
}
impl SyncResponse {
///
pub fn new() -> Self{
SyncResponse {
builder: ResponseBuilder::new(),
body: Box::new(EMPTY_BODY),
}
}
/// Set the HTTP status for this response.
///
/// This function will configure the HTTP status code of the `Response` that
/// will be returned from `Builder::build`.
///
/// By default this is `200`.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
///
/// let response = SyncResponse::new()
/// .status(200)
/// .build_response()
/// .unwrap();
/// ```
pub fn status<T>(&mut self, status: T) -> &mut SyncResponse
where StatusCode: HttpTryFrom<T>,
{
self.builder.status(status);
self
}
/// Set the HTTP version for this response.
///
/// This function will configure the HTTP version of the `Response` that
/// will be returned from `Builder::build`.
///
/// By default this is HTTP/1.1
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
///
/// let response = SyncResponse::new()
/// .version(Version::HTTP_2)
/// .build_response()
/// .unwrap();
/// ```
pub fn version(&mut self, version: Version) -> &mut SyncResponse {
self.builder.version(version);
self
}
/// Appends a header to this response builder.
///
/// This function will append the provided key/value as a header to the
/// internal `HeaderMap` being constructed. Essentially this is equivalent
/// to calling `HeaderMap::append`.
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
///
/// let response = SyncResponse::new()
/// .header("Content-Type", "text/html")
/// .header("X-Custom-Foo", "bar")
/// .build_response()
/// .unwrap();
/// ```
pub fn header<K, V>(&mut self, key: K, value: V) -> &mut SyncResponse
where header::HeaderName: HttpTryFrom<K>,
header::HeaderValue: HttpTryFrom<V>
{
self.builder.header(key, value);
self
}
/// A convinient function to constuct the response headers from a Headers struct
pub fn parsed_header(&mut self, headers: header::Headers) -> &mut SyncResponse {
let map: header::HeaderMap = headers.into();
for header in map {
if let (Some(name), value) = header {
self.builder.header(name, value);
}
}
self
}
/// Adds an extension to this builder
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
///
/// let response = SyncResponse::new()
/// .extension("My Extension")
/// .build_response()
/// .unwrap();
///
/// assert_eq!(response.extensions().get::<&'static str>(),
/// Some(&"My Extension"));
/// ```
pub fn extension<T>(&mut self, extension: T) -> &mut SyncResponse
where T: Any + Send + Sync + 'static,
{
self.builder.extension(extension);
self
}
/// Adds a body to a response
///
/// # Examples
///
/// ```rust,no_run
/// # use saphir::*;
/// # use saphir::headers::*;
///
/// let response = SyncResponse::new()
/// .body(b"this is a payload")
/// .build_response()
/// .unwrap();
/// ```
pub fn body<B: 'static + ToBody>(&mut self, body: B) -> &mut SyncResponse {
self.body = Box::new(body);
self
}
///
pub fn build_response(self) -> Result<Response<Body>, ::http_types::Error> {
let SyncResponse { mut builder, body } = self;
let b: Body = body.to_body();
builder.body(b)
}
}
///
pub trait ToBody {
///
fn to_body(&self) -> Body;
}
impl<I> ToBody for I where I: Into<Body> + Clone {
fn to_body(&self) -> Body {
self.clone().into()
}
}