Add documentation
This commit is contained in:
parent
1922c99979
commit
269d405bb5
47
src/lib.rs
47
src/lib.rs
@ -41,18 +41,19 @@
|
|||||||
//!
|
//!
|
||||||
//! # Server behavior
|
//! # Server behavior
|
||||||
//!
|
//!
|
||||||
//! The Server is started with [Server::run()](struct.Server.html#method.run).
|
//! The Server is started with [run()](struct.Server.html#method.run).
|
||||||
//!
|
//!
|
||||||
//! The server will run in a background thread until it's dropped. Once dropped
|
//! The server will run in a background thread until it's dropped. Once dropped
|
||||||
//! it will assert that every configured expectation has been met or will panic.
|
//! it will assert that every configured expectation has been met or will panic.
|
||||||
//! You can also use [server.verify_and_clear()](struct.Server.html#method.verify_and_clear)
|
//! You can also use [verify_and_clear()](struct.Server.html#method.verify_and_clear)
|
||||||
//! to assert and clear the expectations while keeping the server running.
|
//! to assert and clear the expectations while keeping the server running.
|
||||||
//!
|
//!
|
||||||
//! [server.addr()](struct.Server.html#method.addr) will return the address the
|
//! [addr()](struct.Server.html#method.addr) will return the address the
|
||||||
//! server is listening on.
|
//! server is listening on.
|
||||||
//!
|
//!
|
||||||
//! [server.url()](struct.Server.html#method.url) will
|
//! [url()](struct.Server.html#method.url) will
|
||||||
//! construct a fully formed http url to the path provided i.e.
|
//! construct a fully formed http url to the path provided i.e.
|
||||||
|
//!
|
||||||
//! `server.url("/foo?key=value") == "https://<server_addr>/foo?key=value"`.
|
//! `server.url("/foo?key=value") == "https://<server_addr>/foo?key=value"`.
|
||||||
//!
|
//!
|
||||||
//! # Defining Expecations
|
//! # Defining Expecations
|
||||||
@ -127,18 +128,22 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Times
|
//! ## Times
|
||||||
//!
|
//!
|
||||||
//! Each expectation defines how many times a matching requests is expected to
|
//! Each expectation defines how many times a matching request is expected to
|
||||||
//! be received. The [Times](enum.Times.html) enum defines the possibility.
|
//! be received. The [Times](enum.Times.html) enum defines the possibility.
|
||||||
//! `Times::Exactly(1)` is the default value of an `Expectation` if one is not
|
//! `Times::Exactly(1)` is the default value of an `Expectation` if one is not
|
||||||
//! specified with the
|
//! specified with the
|
||||||
//! [Expectation.times()](struct.Expectation.html#method.times) method.
|
//! [times()](struct.ExpectationBuilder.html#method.times) method.
|
||||||
|
//!
|
||||||
|
//! The server will respond to any requests that violate the times request with
|
||||||
|
//! a 500 status code and the server will subsequently panic on Drop.
|
||||||
//!
|
//!
|
||||||
//! ## Responder
|
//! ## Responder
|
||||||
//!
|
//!
|
||||||
//! responders define how the server will respond to a matched request. There
|
//! Responders define how the server will respond to a matched request. There
|
||||||
//! are a number of implemented responders within the responders module. In
|
//! are a number of implemented responders within the responders module. In
|
||||||
//! addition to the predefined responders you can provide any
|
//! addition to the predefined responders you can provide any
|
||||||
//! hyper::Response<Vec<u8>> or obviously implement your own Responder.
|
//! `hyper::Response` with a body that can be cloned or implement your own
|
||||||
|
//! Responder.
|
||||||
//!
|
//!
|
||||||
//! ## Responder example
|
//! ## Responder example
|
||||||
//!
|
//!
|
||||||
@ -165,26 +170,38 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
//#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
// hidden from docs here because it's re-rexported from the mappers module.
|
/// true if all the provided matchers return true.
|
||||||
#[doc(hidden)]
|
///
|
||||||
|
/// The macro exists to conveniently box a list of mappers and put them into a
|
||||||
|
/// `Vec<Box<dyn Mapper>>`. The translation is:
|
||||||
|
///
|
||||||
|
/// `all_of![a, b] => all_of(vec![Box::new(a), Box::new(b)])`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! all_of {
|
macro_rules! all_of {
|
||||||
($($x:expr),*) => ($crate::mappers::all_of($crate::vec_of_boxes![$($x),*]));
|
($($x:expr),*) => ($crate::mappers::all_of($crate::vec_of_boxes![$($x),*]));
|
||||||
($($x:expr,)*) => ($crate::all_of![$($x),*]);
|
($($x:expr,)*) => ($crate::all_of![$($x),*]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hidden from docs here because it's re-rexported from the mappers module.
|
/// true if any of the provided matchers return true.
|
||||||
#[doc(hidden)]
|
///
|
||||||
|
/// The macro exists to conveniently box a list of mappers and put them into a
|
||||||
|
/// `Vec<Box<dyn Mapper>>`. The translation is:
|
||||||
|
///
|
||||||
|
/// `any_of![a, b] => any_of(vec![Box::new(a), Box::new(b)])`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! any_of {
|
macro_rules! any_of {
|
||||||
($($x:expr),*) => ($crate::mappers::any_of($crate::vec_of_boxes![$($x),*]));
|
($($x:expr),*) => ($crate::mappers::any_of($crate::vec_of_boxes![$($x),*]));
|
||||||
($($x:expr,)*) => ($crate::any_of![$($x),*]);
|
($($x:expr,)*) => ($crate::any_of![$($x),*]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hidden from docs here because it's re-rexported from the responders module.
|
/// a Responder that cycles through a list of responses.
|
||||||
#[doc(hidden)]
|
///
|
||||||
|
/// The macro exists to conveniently box a list of responders and put them into a
|
||||||
|
/// `Vec<Box<dyn Responder>>`. The translation is:
|
||||||
|
///
|
||||||
|
/// `cycle![a, b] => cycle(vec![Box::new(a), Box::new(b)])`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! cycle {
|
macro_rules! cycle {
|
||||||
($($x:expr),*) => ($crate::responders::cycle($crate::vec_of_boxes![$($x),*]));
|
($($x:expr),*) => ($crate::responders::cycle($crate::vec_of_boxes![$($x),*]));
|
||||||
|
|||||||
@ -1,30 +1,54 @@
|
|||||||
|
//! Mapper implementations.
|
||||||
|
//!
|
||||||
|
//! This module contains mappers for composing a set of operations. The result
|
||||||
|
//! of the composition usually results in a boolean. Any `Mapper` that results in a
|
||||||
|
//! boolean value also implemens `Matcher`.
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
// import the any_of and all_of macros from crate root so they are accessible if
|
// import the any_of and all_of macros from crate root so they are accessible if
|
||||||
// people glob import this module.
|
// people glob import this module.
|
||||||
|
/// Accept a list of matchers and returns true if all matchers are true.
|
||||||
|
#[doc(inline)]
|
||||||
pub use crate::all_of;
|
pub use crate::all_of;
|
||||||
|
/// Accept a list of matchers and returns true if any matcher is true.
|
||||||
|
#[doc(inline)]
|
||||||
pub use crate::any_of;
|
pub use crate::any_of;
|
||||||
|
|
||||||
pub mod request;
|
pub mod request;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod sequence;
|
pub mod sequence;
|
||||||
|
|
||||||
|
/// The core trait. Defines how an input value should be turned into an output
|
||||||
|
/// value. This allows for a flexible pattern of composition where two or more
|
||||||
|
/// mappers are chained together to form a readable and flexible manipulation.
|
||||||
|
///
|
||||||
|
/// There is a special case of a Mapper that outputs a bool that is called a
|
||||||
|
/// Matcher.
|
||||||
pub trait Mapper<IN>: Send + fmt::Debug
|
pub trait Mapper<IN>: Send + fmt::Debug
|
||||||
where
|
where
|
||||||
IN: ?Sized,
|
IN: ?Sized,
|
||||||
{
|
{
|
||||||
|
/// The output type.
|
||||||
type Out;
|
type Out;
|
||||||
|
|
||||||
|
/// Map an input to output.
|
||||||
fn map(&mut self, input: &IN) -> Self::Out;
|
fn map(&mut self, input: &IN) -> Self::Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matcher is just a special case of Mapper that returns a boolean. Simply
|
/// Matcher is just a special case of Mapper that returns a boolean. It simply
|
||||||
// provides the `matches` method rather than `map` as that reads a little
|
/// provides the `matches` method rather than `map` as that reads a little
|
||||||
// better.
|
/// better.
|
||||||
|
///
|
||||||
|
/// There is a blanket implementation for all Mappers that output bool values.
|
||||||
|
/// You should never implement Matcher yourself, instead implement Mapper with a
|
||||||
|
/// bool Out parameter.
|
||||||
pub trait Matcher<IN>: Send + fmt::Debug
|
pub trait Matcher<IN>: Send + fmt::Debug
|
||||||
where
|
where
|
||||||
IN: ?Sized,
|
IN: ?Sized,
|
||||||
{
|
{
|
||||||
|
/// true if the input matches.
|
||||||
fn matches(&mut self, input: &IN) -> bool;
|
fn matches(&mut self, input: &IN) -> bool;
|
||||||
}
|
}
|
||||||
impl<T, IN> Matcher<IN> for T
|
impl<T, IN> Matcher<IN> for T
|
||||||
@ -36,9 +60,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Always true.
|
||||||
pub fn any() -> Any {
|
pub fn any() -> Any {
|
||||||
Any
|
Any
|
||||||
}
|
}
|
||||||
|
/// The `Any` mapper returned by [any()](fn.any.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Any;
|
pub struct Any;
|
||||||
impl<IN> Mapper<IN> for Any
|
impl<IN> Mapper<IN> for Any
|
||||||
@ -52,9 +78,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// true if the input is equal to value.
|
||||||
pub fn eq<T>(value: T) -> Eq<T> {
|
pub fn eq<T>(value: T) -> Eq<T> {
|
||||||
Eq(value)
|
Eq(value)
|
||||||
}
|
}
|
||||||
|
/// The `Eq` mapper returned by [eq()](fn.eq.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Eq<T>(T);
|
pub struct Eq<T>(T);
|
||||||
impl<IN, T> Mapper<IN> for Eq<T>
|
impl<IN, T> Mapper<IN> for Eq<T>
|
||||||
@ -69,9 +97,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Call Deref::deref() on the input and pass it to the next mapper.
|
||||||
pub fn deref<C>(inner: C) -> Deref<C> {
|
pub fn deref<C>(inner: C) -> Deref<C> {
|
||||||
Deref(inner)
|
Deref(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Deref` mapper returned by [deref()](fn.deref.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Deref<C>(C);
|
pub struct Deref<C>(C);
|
||||||
impl<C, IN> Mapper<IN> for Deref<C>
|
impl<C, IN> Mapper<IN> for Deref<C>
|
||||||
@ -86,7 +116,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a regex.
|
||||||
|
///
|
||||||
|
/// This trait may panic if the regex failed to build.
|
||||||
pub trait IntoRegex {
|
pub trait IntoRegex {
|
||||||
|
/// turn self into a regex.
|
||||||
fn into_regex(self) -> regex::bytes::Regex;
|
fn into_regex(self) -> regex::bytes::Regex;
|
||||||
}
|
}
|
||||||
impl IntoRegex for &str {
|
impl IntoRegex for &str {
|
||||||
@ -110,10 +144,12 @@ impl IntoRegex for regex::bytes::Regex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// true if the input matches the regex provided.
|
||||||
pub fn matches(value: impl IntoRegex) -> Matches {
|
pub fn matches(value: impl IntoRegex) -> Matches {
|
||||||
//let regex = regex::bytes::Regex::new(value).expect("failed to create regex");
|
//let regex = regex::bytes::Regex::new(value).expect("failed to create regex");
|
||||||
Matches(value.into_regex())
|
Matches(value.into_regex())
|
||||||
}
|
}
|
||||||
|
/// The `Matches` mapper returned by [matches()](fn.matches.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Matches(regex::bytes::Regex);
|
pub struct Matches(regex::bytes::Regex);
|
||||||
impl<IN> Mapper<IN> for Matches
|
impl<IN> Mapper<IN> for Matches
|
||||||
@ -127,9 +163,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// invert the result of the inner mapper.
|
||||||
pub fn not<C>(inner: C) -> Not<C> {
|
pub fn not<C>(inner: C) -> Not<C> {
|
||||||
Not(inner)
|
Not(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Not` mapper returned by [not()](fn.not.html)
|
||||||
pub struct Not<C>(C);
|
pub struct Not<C>(C);
|
||||||
impl<C, IN> Mapper<IN> for Not<C>
|
impl<C, IN> Mapper<IN> for Not<C>
|
||||||
where
|
where
|
||||||
@ -151,6 +189,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// true if all the provided matchers return true. See the `all_of!` macro for
|
||||||
|
/// convenient usage.
|
||||||
pub fn all_of<IN>(inner: Vec<Box<dyn Mapper<IN, Out = bool>>>) -> AllOf<IN>
|
pub fn all_of<IN>(inner: Vec<Box<dyn Mapper<IN, Out = bool>>>) -> AllOf<IN>
|
||||||
where
|
where
|
||||||
IN: fmt::Debug + ?Sized,
|
IN: fmt::Debug + ?Sized,
|
||||||
@ -158,6 +198,7 @@ where
|
|||||||
AllOf(inner)
|
AllOf(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `AllOf` mapper returned by [all_of()](fn.all_of.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AllOf<IN>(Vec<Box<dyn Mapper<IN, Out = bool>>>)
|
pub struct AllOf<IN>(Vec<Box<dyn Mapper<IN, Out = bool>>>)
|
||||||
where
|
where
|
||||||
@ -173,12 +214,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// true if any of the provided matchers returns true. See the `any_of!` macro
|
||||||
|
/// for convenient usage.
|
||||||
pub fn any_of<IN>(inner: Vec<Box<dyn Mapper<IN, Out = bool>>>) -> AnyOf<IN>
|
pub fn any_of<IN>(inner: Vec<Box<dyn Mapper<IN, Out = bool>>>) -> AnyOf<IN>
|
||||||
where
|
where
|
||||||
IN: fmt::Debug + ?Sized,
|
IN: fmt::Debug + ?Sized,
|
||||||
{
|
{
|
||||||
AnyOf(inner)
|
AnyOf(inner)
|
||||||
}
|
}
|
||||||
|
/// The `AnyOf` mapper returned by [any_of()](fn.any_of.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AnyOf<IN>(Vec<Box<dyn Mapper<IN, Out = bool>>>)
|
pub struct AnyOf<IN>(Vec<Box<dyn Mapper<IN, Out = bool>>>)
|
||||||
where
|
where
|
||||||
@ -194,12 +238,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url_decoded<C>(inner: C) -> UrlDecoded<C>
|
/// url decode the input and pass the resulting slice of key-value pairs to the next mapper.
|
||||||
where
|
pub fn url_decoded<C>(inner: C) -> UrlDecoded<C> {
|
||||||
C: Mapper<[(String, String)]>,
|
|
||||||
{
|
|
||||||
UrlDecoded(inner)
|
UrlDecoded(inner)
|
||||||
}
|
}
|
||||||
|
/// The `UrlDecoded` mapper returned by [url_decoded()](fn.url_decoded.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UrlDecoded<C>(C);
|
pub struct UrlDecoded<C>(C);
|
||||||
impl<IN, C> Mapper<IN> for UrlDecoded<C>
|
impl<IN, C> Mapper<IN> for UrlDecoded<C>
|
||||||
@ -217,12 +260,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn json_decoded<C>(inner: C) -> JsonDecoded<C>
|
/// json decode the input and pass the resulting serde_json::Value to the next
|
||||||
where
|
/// mapper.
|
||||||
C: Mapper<serde_json::Value>,
|
///
|
||||||
{
|
/// If the input can't be decoded a serde_json::Value::Null is passed to the next
|
||||||
|
/// mapper.
|
||||||
|
pub fn json_decoded<C>(inner: C) -> JsonDecoded<C> {
|
||||||
JsonDecoded(inner)
|
JsonDecoded(inner)
|
||||||
}
|
}
|
||||||
|
/// The `JsonDecoded` mapper returned by [json_decoded()](fn.json_decoded.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JsonDecoded<C>(C);
|
pub struct JsonDecoded<C>(C);
|
||||||
impl<IN, C> Mapper<IN> for JsonDecoded<C>
|
impl<IN, C> Mapper<IN> for JsonDecoded<C>
|
||||||
@ -239,12 +285,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// lowercase the input and pass it to the next mapper.
|
||||||
pub fn lowercase<C>(inner: C) -> Lowercase<C>
|
pub fn lowercase<C>(inner: C) -> Lowercase<C>
|
||||||
where
|
where
|
||||||
C: Mapper<[u8]>,
|
C: Mapper<[u8]>,
|
||||||
{
|
{
|
||||||
Lowercase(inner)
|
Lowercase(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Lowercase` mapper returned by [lowercase()](fn.lowercase.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Lowercase<C>(C);
|
pub struct Lowercase<C>(C);
|
||||||
impl<IN, C> Mapper<IN> for Lowercase<C>
|
impl<IN, C> Mapper<IN> for Lowercase<C>
|
||||||
@ -260,9 +308,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// pass the input to the provided `Fn(T) -> bool` and return the result.
|
||||||
pub fn map_fn<F>(f: F) -> MapFn<F> {
|
pub fn map_fn<F>(f: F) -> MapFn<F> {
|
||||||
MapFn(f)
|
MapFn(f)
|
||||||
}
|
}
|
||||||
|
/// The `MapFn` mapper returned by [map_fn()](fn.map_fn.html)
|
||||||
pub struct MapFn<F>(F);
|
pub struct MapFn<F>(F);
|
||||||
impl<IN, F> Mapper<IN> for MapFn<F>
|
impl<IN, F> Mapper<IN> for MapFn<F>
|
||||||
where
|
where
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
|
//! Mappers that extract information from HTTP requests.
|
||||||
|
|
||||||
use super::Mapper;
|
use super::Mapper;
|
||||||
|
|
||||||
pub fn method<C>(inner: C) -> Method<C>
|
/// Extract the method from the HTTP request and pass it to the next mapper.
|
||||||
where
|
pub fn method<C>(inner: C) -> Method<C> {
|
||||||
C: Mapper<str>,
|
|
||||||
{
|
|
||||||
Method(inner)
|
Method(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Method` mapper returned by [method()](fn.method.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Method<C>(C);
|
pub struct Method<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Request<B>> for Method<C>
|
impl<C, B> Mapper<hyper::Request<B>> for Method<C>
|
||||||
@ -19,12 +20,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path<C>(inner: C) -> Path<C>
|
/// Extract the path from the HTTP request and pass it to the next mapper.
|
||||||
where
|
pub fn path<C>(inner: C) -> Path<C> {
|
||||||
C: Mapper<str>,
|
|
||||||
{
|
|
||||||
Path(inner)
|
Path(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Path` mapper returned by [path()](fn.path.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Path<C>(C);
|
pub struct Path<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Request<B>> for Path<C>
|
impl<C, B> Mapper<hyper::Request<B>> for Path<C>
|
||||||
@ -38,12 +38,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query<C>(inner: C) -> Query<C>
|
/// Extract the query from the HTTP request and pass it to the next mapper.
|
||||||
where
|
pub fn query<C>(inner: C) -> Query<C> {
|
||||||
C: Mapper<str>,
|
|
||||||
{
|
|
||||||
Query(inner)
|
Query(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Query` mapper returned by [query()](fn.query.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Query<C>(C);
|
pub struct Query<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Request<B>> for Query<C>
|
impl<C, B> Mapper<hyper::Request<B>> for Query<C>
|
||||||
@ -57,12 +56,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn headers<C>(inner: C) -> Headers<C>
|
/// Extract the headers from the HTTP request and pass the sequence to the next
|
||||||
where
|
/// mapper.
|
||||||
C: Mapper<[(Vec<u8>, Vec<u8>)]>,
|
pub fn headers<C>(inner: C) -> Headers<C> {
|
||||||
{
|
|
||||||
Headers(inner)
|
Headers(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Headers` mapper returned by [headers()](fn.headers.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Headers<C>(C);
|
pub struct Headers<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Request<B>> for Headers<C>
|
impl<C, B> Mapper<hyper::Request<B>> for Headers<C>
|
||||||
@ -81,9 +80,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract the body from the HTTP request and pass it to the next mapper.
|
||||||
pub fn body<C>(inner: C) -> Body<C> {
|
pub fn body<C>(inner: C) -> Body<C> {
|
||||||
Body(inner)
|
Body(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Body` mapper returned by [body()](fn.body.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Body<C>(C);
|
pub struct Body<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Request<B>> for Body<C>
|
impl<C, B> Mapper<hyper::Request<B>> for Body<C>
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
|
//! Mappers that extract information from HTTP responses.
|
||||||
|
|
||||||
use super::Mapper;
|
use super::Mapper;
|
||||||
|
|
||||||
pub fn status_code<C>(inner: C) -> StatusCode<C>
|
/// Extract the status code from the HTTP response and pass it to the next mapper.
|
||||||
where
|
pub fn status_code<C>(inner: C) -> StatusCode<C> {
|
||||||
C: Mapper<u16>,
|
|
||||||
{
|
|
||||||
StatusCode(inner)
|
StatusCode(inner)
|
||||||
}
|
}
|
||||||
|
/// The `StatusCode` mapper returned by [status_code()](fn.status_code.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StatusCode<C>(C);
|
pub struct StatusCode<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Response<B>> for StatusCode<C>
|
impl<C, B> Mapper<hyper::Response<B>> for StatusCode<C>
|
||||||
@ -19,12 +20,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn headers<C>(inner: C) -> Headers<C>
|
/// Extract the headers from the HTTP response and pass the sequence to the next
|
||||||
where
|
/// mapper.
|
||||||
C: Mapper<[(Vec<u8>, Vec<u8>)]>,
|
pub fn headers<C>(inner: C) -> Headers<C> {
|
||||||
{
|
|
||||||
Headers(inner)
|
Headers(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Headers` mapper returned by [headers()](fn.headers.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Headers<C>(C);
|
pub struct Headers<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Response<B>> for Headers<C>
|
impl<C, B> Mapper<hyper::Response<B>> for Headers<C>
|
||||||
@ -43,9 +44,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract the body from the HTTP response and pass it to the next mapper.
|
||||||
pub fn body<C>(inner: C) -> Body<C> {
|
pub fn body<C>(inner: C) -> Body<C> {
|
||||||
Body(inner)
|
Body(inner)
|
||||||
}
|
}
|
||||||
|
/// The `Body` mapper returned by [body()](fn.body.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Body<C>(C);
|
pub struct Body<C>(C);
|
||||||
impl<C, B> Mapper<hyper::Response<B>> for Body<C>
|
impl<C, B> Mapper<hyper::Response<B>> for Body<C>
|
||||||
|
|||||||
@ -1,16 +1,26 @@
|
|||||||
|
//! Responder implementations.
|
||||||
|
//!
|
||||||
|
//! Reponders determine how the server will respond.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
// import the cycle macro so that it's available if people glob import this module.
|
||||||
|
#[doc(inline)]
|
||||||
pub use crate::cycle;
|
pub use crate::cycle;
|
||||||
|
|
||||||
|
/// Respond with an HTTP response.
|
||||||
pub trait Responder: Send + fmt::Debug {
|
pub trait Responder: Send + fmt::Debug {
|
||||||
|
/// Return a future that outputs an HTTP response.
|
||||||
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>>;
|
fn respond(&mut self) -> Pin<Box<dyn Future<Output = http::Response<hyper::Body>> + Send>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// respond with the provided status code.
|
||||||
pub fn status_code(code: u16) -> impl Responder {
|
pub fn status_code(code: u16) -> impl Responder {
|
||||||
StatusCode(code)
|
StatusCode(code)
|
||||||
}
|
}
|
||||||
|
/// The `StatusCode` responder returned by [status_code()](fn.status_code.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StatusCode(u16);
|
pub struct StatusCode(u16);
|
||||||
impl Responder for StatusCode {
|
impl Responder for StatusCode {
|
||||||
@ -25,12 +35,17 @@ impl Responder for StatusCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// respond with a body that is the json encoding of data.
|
||||||
|
///
|
||||||
|
/// The status code will be `200` and the content-type will be
|
||||||
|
/// `application/json`.
|
||||||
pub fn json_encoded<T>(data: T) -> impl Responder
|
pub fn json_encoded<T>(data: T) -> impl Responder
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
JsonEncoded(serde_json::to_string(&data).unwrap())
|
JsonEncoded(serde_json::to_string(&data).unwrap())
|
||||||
}
|
}
|
||||||
|
/// The `JsonEncoded` responder returned by [json_encoded()](fn.json_encoded.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JsonEncoded(String);
|
pub struct JsonEncoded(String);
|
||||||
impl Responder for JsonEncoded {
|
impl Responder for JsonEncoded {
|
||||||
@ -46,12 +61,17 @@ impl Responder for JsonEncoded {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// respond with a body that is the url encoding of data.
|
||||||
|
///
|
||||||
|
/// The status code will be `200` and the content-type will be
|
||||||
|
/// `application/x-www-form-urlencoded`.
|
||||||
pub fn url_encoded<T>(data: T) -> impl Responder
|
pub fn url_encoded<T>(data: T) -> impl Responder
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
UrlEncoded(serde_urlencoded::to_string(&data).unwrap())
|
UrlEncoded(serde_urlencoded::to_string(&data).unwrap())
|
||||||
}
|
}
|
||||||
|
/// The `UrlEncoded` responder returned by [url_encoded()](fn.url_encoded.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UrlEncoded(String);
|
pub struct UrlEncoded(String);
|
||||||
impl Responder for UrlEncoded {
|
impl Responder for UrlEncoded {
|
||||||
@ -87,12 +107,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cycle through the provided list of responders.
|
||||||
pub fn cycle(responders: Vec<Box<dyn Responder>>) -> impl Responder {
|
pub fn cycle(responders: Vec<Box<dyn Responder>>) -> impl Responder {
|
||||||
if responders.is_empty() {
|
if responders.is_empty() {
|
||||||
panic!("empty vector provided to cycle");
|
panic!("empty vector provided to cycle");
|
||||||
}
|
}
|
||||||
Cycle { idx: 0, responders }
|
Cycle { idx: 0, responders }
|
||||||
}
|
}
|
||||||
|
/// The `Cycle` responder returned by [cycle()](fn.cycle.html)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Cycle {
|
pub struct Cycle {
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user