This commit is contained in:
nora 2023-03-07 15:19:06 +01:00
parent 0b89e245d9
commit e1ebd97c91
73 changed files with 3822 additions and 3822 deletions

View file

@ -2,7 +2,7 @@ use std::convert::Infallible;
use std::error::Error as StdError;
use std::fmt;
type BoxError = Box<dyn std::error::Error + Send + Sync>;
/// Errors that can happen inside warp.
pub struct Error {
inner: BoxError,
}

View file

@ -5,25 +5,25 @@ use std::sync::Arc;
use super::{Filter, FilterBase, Internal, Tuple};
use crate::reject::Rejection;
/// A type representing a boxed `Filter` trait object.
///
/// The filter inside is a dynamic trait object. The purpose of this type is
/// to ease returning `Filter`s from other functions.
///
/// To create one, call `Filter::boxed` on any filter.
///
/// # Examples
///
/// ```
/// use warp::{Filter, filters::BoxedFilter, Reply};
///
/// pub fn assets_filter() -> BoxedFilter<(impl Reply,)> {
/// warp::path("assets")
/// .and(warp::fs::dir("./assets"))
/// .boxed()
/// }
/// ```
///
pub struct BoxedFilter<T: Tuple> {
filter: Arc<
dyn Filter<

View file

@ -45,47 +45,47 @@ pub trait FilterBase {
}
#[allow(missing_debug_implementations)]
pub struct Internal;
/// Composable request filters.
///
/// A `Filter` can optionally extract some data from a request, combine
/// it with others, mutate it, and return back some value as a reply. The
/// power of `Filter`s come from being able to isolate small subsets, and then
/// chain and reuse them in various parts of your app.
///
/// # Extracting Tuples
///
/// You may notice that several of these filters extract some tuple, often
/// times a tuple of just 1 item! Why?
///
/// If a filter extracts a `(String,)`, that simply means that it
/// extracts a `String`. If you were to `map` the filter, the argument type
/// would be exactly that, just a `String`.
///
/// What is it? It's just some type magic that allows for automatic combining
/// and flattening of tuples. Without it, combining two filters together with
/// `and`, where one extracted `()`, and another `String`, would mean the
/// `map` would be given a single argument of `((), String,)`, which is just
/// no fun.
pub trait Filter: FilterBase {
/// Composes a new `Filter` that requires both this and the other to filter a request.
///
/// Additionally, this will join together the extracted values of both
/// filters, so that `map` and `and_then` receive them as separate arguments.
///
/// If a `Filter` extracts nothing (so, `()`), combining with any other
/// filter will simply discard the `()`. If a `Filter` extracts one or
/// more items, combining will mean it extracts the values of itself
/// combined with the other.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Match `/hello/:name`...
/// warp::path("hello")
/// .and(warp::path::param::<String>());
/// ```
fn and<F>(self, other: F) -> And<Self, F>
where
Self: Sized,
@ -95,18 +95,18 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Composes a new `Filter` of either this or the other filter.
///
/// # Example
///
/// ```
/// use std::net::SocketAddr;
/// use warp::Filter;
///
/// // Match either `/:u32` or `/:socketaddr`
/// warp::path::param::<u32>()
/// .or(warp::path::param::<SocketAddr>());
/// ```
fn or<F>(self, other: F) -> Or<Self, F>
where
Self: Filter<Error = Rejection> + Sized,
@ -115,47 +115,47 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Composes this `Filter` with a function receiving the extracted value.
///
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Map `/:id`
/// warp::path::param().map(|id: u64| {
/// format!("Hello #{}", id)
/// });
/// ```
///
/// # `Func`
///
/// The generic `Func` trait is implemented for any function that receives
/// the same arguments as this `Filter` extracts. In practice, this
/// shouldn't ever bother you, and simply makes things feel more natural.
///
/// For example, if three `Filter`s were combined together, suppose one
/// extracts nothing (so `()`), and the other two extract two integers,
/// a function that accepts exactly two integer arguments is allowed.
/// Specifically, any `Fn(u32, u32)`.
///
/// Without `Product` and `Func`, this would be a lot messier. First of
/// all, the `()`s couldn't be discarded, and the tuples would be nested.
/// So, instead, you'd need to pass an `Fn(((), (u32, u32)))`. That's just
/// a single argument. Bleck!
///
/// Even worse, the tuples would shuffle the types around depending on
/// the exact invocation of `and`s. So, `unit.and(int).and(int)` would
/// result in a different extracted type from `unit.and(int.and(int))`,
/// or from `int.and(unit).and(int)`. If you changed around the order
/// of filters, while still having them be semantically equivalent, you'd
/// need to update all your `map`s as well.
///
/// `Product`, `HList`, and `Func` do all the heavy work so that none of
/// this is a bother to you. What's more, the types are enforced at
/// compile-time, and tuple flattening is optimized away to nothing by
/// LLVM.
fn map<F>(self, fun: F) -> Map<Self, F>
where
Self: Sized,
@ -163,21 +163,21 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Composes this `Filter` with an async function receiving
/// the extracted value.
///
/// The function should return some `Future` type.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Map `/:id`
/// warp::path::param().then(|id: u64| async move {
/// format!("Hello #{}", id)
/// });
/// ```
fn then<F>(self, fun: F) -> Then<Self, F>
where
Self: Sized,
@ -186,32 +186,32 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Composes this `Filter` with a fallible async function receiving
/// the extracted value.
///
/// The function should return some `TryFuture` type.
///
/// The `Error` type of the return `Future` needs be a `Rejection`, which
/// means most futures will need to have their error mapped into one.
///
/// Rejections are meant to say "this filter didn't accept the request,
/// maybe another can". So for application-level errors, consider using
/// [`Filter::then`] instead.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Validate after `/:id`
/// warp::path::param().and_then(|id: u64| async move {
/// if id != 0 {
/// Ok(format!("Hello #{}", id))
/// } else {
/// Err(warp::reject::not_found())
/// }
/// });
/// ```
fn and_then<F>(self, fun: F) -> AndThen<Self, F>
where
Self: Sized,
@ -221,10 +221,10 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Compose this `Filter` with a function receiving an error.
///
/// The function should return some `TryFuture` type yielding the
/// same item and error types.
fn or_else<F>(self, fun: F) -> OrElse<Self, F>
where
Self: Filter<Error = Rejection> + Sized,
@ -234,13 +234,13 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Compose this `Filter` with a function receiving an error and
/// returning a *new* type, instead of the *same* type.
///
/// This is useful for "customizing" rejections into new response types.
/// See also the [rejections example][ex].
///
/// [ex]: https://github.com/seanmonstar/warp/blob/master/examples/rejections.rs
fn recover<F>(self, fun: F) -> Recover<Self, F>
where
Self: Filter<Error = Rejection> + Sized,
@ -250,28 +250,28 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Unifies the extracted value of `Filter`s composed with `or`.
///
/// When a `Filter` extracts some `Either<T, T>`, where both sides
/// are the same type, this combinator can be used to grab the
/// inner value, regardless of which side of `Either` it was. This
/// is useful for values that could be extracted from multiple parts
/// of a request, and the exact place isn't important.
///
/// # Example
///
/// ```rust
/// use std::net::SocketAddr;
/// use warp::Filter;
///
/// let client_ip = warp::header("x-real-ip")
/// .or(warp::header("x-forwarded-for"))
/// .unify()
/// .map(|ip: SocketAddr| {
/// // Get the IP from either header,
/// // and unify into the inner type.
/// });
/// ```
fn unify<T>(self) -> Unify<Self>
where
Self: Filter<Extract = (Either<T, T>,)> + Sized,
@ -279,41 +279,41 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Convenience method to remove one layer of tupling.
///
/// This is useful for when things like `map` don't return a new value,
/// but just `()`, since warp will wrap it up into a `((),)`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::path::param()
/// .map(|num: u64| {
/// println!("just logging: {}", num);
/// // returning "nothing"
/// })
/// .untuple_one()
/// .map(|| {
/// println!("the ((),) was removed");
/// warp::reply()
/// });
/// ```
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(|| {
/// // wanting to return a tuple
/// (true, 33)
/// })
/// .untuple_one()
/// .map(|is_enabled: bool, count: i32| {
/// println!("untupled: ({}, {})", is_enabled, count);
/// });
/// ```
fn untuple_one<T>(self) -> UntupleOne<Self>
where
Self: Filter<Extract = (T,)> + Sized,
@ -321,22 +321,22 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Wraps the current filter with some wrapper.
///
/// The wrapper may do some preparation work before starting this filter,
/// and may do post-processing after the filter completes.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(warp::reply);
///
/// // Wrap the route with a log wrapper.
/// let route = route.with(warp::log("example"));
/// ```
fn with<W>(self, wrapper: W) -> W::Wrapped
where
Self: Sized,
@ -344,30 +344,30 @@ pub trait Filter: FilterBase {
{
loop {}
}
/// Boxes this filter into a trait object, making it easier to name the type.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// fn impl_reply() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
/// warp::any()
/// .map(warp::reply)
/// .boxed()
/// }
///
/// fn named_i32() -> warp::filters::BoxedFilter<(i32,)> {
/// warp::path::param::<i32>()
/// .boxed()
/// }
///
/// fn named_and() -> warp::filters::BoxedFilter<(i32, String)> {
/// warp::path::param::<i32>()
/// .and(warp::header::<String>("host"))
/// .boxed()
/// }
/// ```
fn boxed(self) -> BoxedFilter<Self::Extract>
where
Self: Sized + Send + Sync + 'static,

View file

@ -10,42 +10,42 @@ use crate::reject::IsReject;
use crate::reply::{Reply, Response};
use crate::route::{Route};
use crate::{Filter, Request};
/// Convert a `Filter` into a `Service`.
///
/// Filters are normally what APIs are built on in warp. However, it can be
/// useful to convert a `Filter` into a [`Service`][Service], such as if
/// further customizing a `hyper::Service`, or if wanting to make use of
/// the greater [Tower][tower] set of middleware.
///
/// # Example
///
/// Running a `warp::Filter` on a regular `hyper::Server`:
///
/// ```
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// use std::convert::Infallible;
/// use warp::Filter;
///
/// // Our Filter...
/// let route = warp::any().map(|| "Hello From Warp!");
///
/// // Convert it into a `Service`...
/// let svc = warp::service(route);
///
/// // Typical hyper setup...
/// let make_svc = hyper::service::make_service_fn(move |_| async move {
/// Ok::<_, Infallible>(svc)
/// });
///
/// hyper::Server::bind(&([127, 0, 0, 1], 3030).into())
/// .serve(make_svc)
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// [Service]: https://docs.rs/hyper/0.13.*/hyper/service/trait.Service.html
/// [tower]: https://docs.rs/tower
pub fn service<F>(filter: F) -> FilteredService<F>
where
F: Filter,

View file

@ -19,19 +19,19 @@ where
T: WrapSealed<F>,
F: Filter,
{}
/// Combines received filter with pre and after filters
///
/// # Example
///
/// ```
/// use crate::warp::Filter;
///
/// let route = warp::any()
/// .map(|| "hello world")
/// .with(warp::wrap_fn(|filter| filter));
/// ```
///
/// You can find the full example in the [usage example](https://github.com/seanmonstar/warp/blob/master/examples/wrapping.rs).
pub fn wrap_fn<F, T, U>(func: F) -> WrapFn<F>
where
F: Fn(T) -> U,

View file

@ -5,22 +5,22 @@ use std::net::SocketAddr;
use crate::filter::{filter_fn_one, Filter};
/// Creates a `Filter` to get the remote address of the connection.
///
/// If the underlying transport doesn't use socket addresses, this will yield
/// `None`.
///
/// # Example
///
/// ```
/// use std::net::SocketAddr;
/// use warp::Filter;
///
/// let route = warp::addr::remote()
/// .map(|addr: Option<SocketAddr>| {
/// println!("remote address = {:?}", addr);
/// });
/// ```
pub fn remote() -> impl Filter<Extract = (Option<SocketAddr>,), Error = Infallible> + Copy {
filter_fn_one(|route| futures_util::future::ok(route.remote_addr()))
}

View file

@ -4,44 +4,44 @@ use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use crate::filter::{Filter, FilterBase, Internal};
/// A filter that matches any route.
///
/// This can be a useful building block to build new filters from,
/// since [`Filter`](crate::Filter) is otherwise a sealed trait.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(|| {
/// "I always return this string!"
/// });
/// ```
///
/// This could allow creating a single `impl Filter` returning a specific
/// reply, that can then be used as the end of several different filter
/// chains.
///
/// Another use case is turning some clone-able resource into a `Filter`,
/// thus allowing to easily `and` it together with others.
///
/// ```
/// use std::sync::Arc;
/// use warp::Filter;
///
/// let state = Arc::new(vec![33, 41]);
/// let with_state = warp::any().map(move || state.clone());
///
/// // Now we could `and` with any other filter:
///
/// let route = warp::path::param()
/// .and(with_state)
/// .map(|param_id: u32, db: Arc<Vec<u32>>| {
/// db.contains(&param_id)
/// });
/// ```
pub fn any() -> impl Filter<Extract = (), Error = Infallible> + Copy {
Any
}

View file

@ -31,20 +31,20 @@ pub(crate) fn body() -> impl Filter<Extract = (Body,), Error = Rejection> + Copy
)
})
}
/// Require a `content-length` header to have a value no greater than some limit.
///
/// Rejects if `content-length` header is missing, is invalid, or has a number
/// larger than the limit provided.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Limit the upload to 4kb...
/// let upload = warp::body::content_length_limit(4096)
/// .and(warp::body::aggregate());
/// ```
pub fn content_length_limit(
limit: u64,
) -> impl Filter<Extract = (), Error = Rejection> + Copy {
@ -66,44 +66,44 @@ pub fn content_length_limit(
})
.untuple_one()
}
/// Create a `Filter` that extracts the request body as a `futures::Stream`.
///
/// If other filters have already extracted the body, this filter will reject
/// with a `500 Internal Server Error`.
///
/// # Warning
///
/// This does not have a default size limit, it would be wise to use one to
/// prevent a overly large request from using too much memory.
pub fn stream() -> impl Filter<
Extract = (impl Stream<Item = Result<impl Buf, crate::Error>>,),
Error = Rejection,
> + Copy {
body().map(|body: Body| BodyStream { body })
}
/// Returns a `Filter` that matches any request and extracts a `Future` of a
/// concatenated body.
///
/// The contents of the body will be flattened into a single contiguous
/// `Bytes`, which may require memory copies. If you don't require a
/// contiguous buffer, using `aggregate` can be give better performance.
///
/// # Warning
///
/// This does not have a default size limit, it would be wise to use one to
/// prevent a overly large request from using too much memory.
///
/// # Example
///
/// ```
/// use warp::{Buf, Filter};
///
/// let route = warp::body::content_length_limit(1024 * 32)
/// .and(warp::body::bytes())
/// .map(|bytes: bytes::Bytes| {
/// println!("bytes = {:?}", bytes);
/// });
/// ```
pub fn bytes() -> impl Filter<Extract = (Bytes,), Error = Rejection> + Copy {
body()
.and_then(|body: hyper::Body| {
@ -114,35 +114,35 @@ pub fn bytes() -> impl Filter<Extract = (Bytes,), Error = Rejection> + Copy {
})
})
}
/// Returns a `Filter` that matches any request and extracts a `Future` of an
/// aggregated body.
///
/// The `Buf` may contain multiple, non-contiguous buffers. This can be more
/// performant (by reducing copies) when receiving large bodies.
///
/// # Warning
///
/// This does not have a default size limit, it would be wise to use one to
/// prevent a overly large request from using too much memory.
///
/// # Example
///
/// ```
/// use warp::{Buf, Filter};
///
/// fn full_body(mut body: impl Buf) {
/// // It could have several non-contiguous slices of memory...
/// while body.has_remaining() {
/// println!("slice = {:?}", body.chunk());
/// let cnt = body.chunk().len();
/// body.advance(cnt);
/// }
/// }
///
/// let route = warp::body::content_length_limit(1024 * 32)
/// .and(warp::body::aggregate())
/// .map(full_body);
/// ```
pub fn aggregate() -> impl Filter<Extract = (impl Buf,), Error = Rejection> + Copy {
body()
.and_then(|body: ::hyper::Body| {
@ -153,26 +153,26 @@ pub fn aggregate() -> impl Filter<Extract = (impl Buf,), Error = Rejection> + Co
})
})
}
/// Returns a `Filter` that matches any request and extracts a `Future` of a
/// JSON-decoded body.
///
/// # Warning
///
/// This does not have a default size limit, it would be wise to use one to
/// prevent a overly large request from using too much memory.
///
/// # Example
///
/// ```
/// use std::collections::HashMap;
/// use warp::Filter;
///
/// let route = warp::body::content_length_limit(1024 * 32)
/// .and(warp::body::json())
/// .map(|simple_map: HashMap<String, String>| {
/// "Got a JSON body!"
/// });
/// ```
pub fn json<T: DeserializeOwned + Send>() -> impl Filter<
Extract = (T,),
Error = Rejection,
@ -187,30 +187,30 @@ pub fn json<T: DeserializeOwned + Send>() -> impl Filter<
})
})
}
/// Returns a `Filter` that matches any request and extracts a
/// `Future` of a form encoded body.
///
/// # Note
///
/// This filter is for the simpler `application/x-www-form-urlencoded` format,
/// not `multipart/form-data`.
///
/// # Warning
///
/// This does not have a default size limit, it would be wise to use one to
/// prevent a overly large request from using too much memory.
///
///
/// ```
/// use std::collections::HashMap;
/// use warp::Filter;
///
/// let route = warp::body::content_length_limit(1024 * 32)
/// .and(warp::body::form())
/// .map(|simple_map: HashMap<String, String>| {
/// "Got a urlencoded body!"
/// });
/// ```
pub fn form<T: DeserializeOwned + Send>() -> impl Filter<
Extract = (T,),
Error = Rejection,
@ -292,7 +292,7 @@ impl Stream for BodyStream {
loop {}
}
}
/// An error used in rejections when deserializing a request body fails.
#[derive(Debug)]
pub struct BodyDeserializeError {
cause: BoxError,

View file

@ -29,58 +29,58 @@ impl From<CompressionAlgo> for HeaderValue {
loop {}
}
}
/// Compression
#[derive(Clone, Copy, Debug)]
pub struct Compression<F> {
func: F,
}
/// Create a wrapping filter that compresses the Body of a [`Response`](crate::reply::Response)
/// using gzip, adding `content-encoding: gzip` to the Response's [`HeaderMap`](hyper::HeaderMap)
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::get()
/// .and(warp::path::end())
/// .and(warp::fs::file("./README.md"))
/// .with(warp::compression::gzip());
/// ```
#[cfg(feature = "compression-gzip")]
pub fn gzip() -> Compression<impl Fn(CompressionProps) -> Response + Copy> {
loop {}
}
/// Create a wrapping filter that compresses the Body of a [`Response`](crate::reply::Response)
/// using deflate, adding `content-encoding: deflate` to the Response's [`HeaderMap`](hyper::HeaderMap)
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::get()
/// .and(warp::path::end())
/// .and(warp::fs::file("./README.md"))
/// .with(warp::compression::deflate());
/// ```
#[cfg(feature = "compression-gzip")]
pub fn deflate() -> Compression<impl Fn(CompressionProps) -> Response + Copy> {
loop {}
}
/// Create a wrapping filter that compresses the Body of a [`Response`](crate::reply::Response)
/// using brotli, adding `content-encoding: br` to the Response's [`HeaderMap`](hyper::HeaderMap)
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::get()
/// .and(warp::path::end())
/// .and(warp::fs::file("./README.md"))
/// .with(warp::compression::brotli());
/// ```
#[cfg(feature = "compression-brotli")]
pub fn brotli() -> Compression<impl Fn(CompressionProps) -> Response + Copy> {
loop {}
@ -109,8 +109,8 @@ mod internal {
use crate::reject::IsReject;
use crate::reply::{Reply, Response};
use super::Compression;
/// A wrapper around any type that implements [`Stream`](futures::Stream) to be
/// compatible with async_compression's Stream based encoders
#[pin_project]
#[derive(Debug)]
pub struct CompressableBody<S, E>
@ -139,7 +139,7 @@ mod internal {
loop {}
}
}
/// Compression Props
#[derive(Debug)]
pub struct CompressionProps {
pub(super) body: CompressableBody<Body, hyper::Error>,

View file

@ -9,9 +9,9 @@ use crate::reject::Rejection;
use std::convert::Infallible;
use std::str::FromStr;
/// Creates a `Filter` that requires a cookie by name.
///
/// If found, extracts the value of the cookie, otherwise rejects.
pub fn cookie<T>(name: &'static str) -> impl Filter<Extract = One<T>, Error = Rejection> + Copy
where
T: FromStr + Send + 'static,
@ -25,10 +25,10 @@ where
})
}
/// Creates a `Filter` that looks for an optional cookie by name.
///
/// If found, extracts the value of the cookie, otherwise continues
/// the request, extracting `None`.
pub fn optional<T>(
name: &'static str,
) -> impl Filter<Extract = One<Option<T>>, Error = Infallible> + Copy

View file

@ -12,40 +12,40 @@ use crate::filter::{Filter, WrapSealed};
use crate::reject::{CombineRejection, Rejection};
use crate::reply::Reply;
use self::internal::{CorsFilter, IntoOrigin, Seconds};
/// Create a wrapping filter that exposes [CORS][] behavior for a wrapped
/// filter.
///
/// [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let cors = warp::cors()
/// .allow_origin("https://hyper.rs")
/// .allow_methods(vec!["GET", "POST", "DELETE"]);
///
/// let route = warp::any()
/// .map(warp::reply)
/// .with(cors);
/// ```
/// If you want to allow any route:
/// ```
/// use warp::Filter;
/// let cors = warp::cors()
/// .allow_any_origin();
/// ```
/// You can find more usage examples [here](https://github.com/seanmonstar/warp/blob/7fa54eaecd0fe12687137372791ff22fc7995766/tests/cors.rs).
pub fn cors() -> Builder {
loop {}
}
/// A wrapping filter constructed via `warp::cors()`.
#[derive(Clone, Debug)]
pub struct Cors {
config: Arc<Configured>,
}
/// A constructed via `warp::cors()`.
#[derive(Clone, Debug)]
pub struct Builder {
credentials: bool,
@ -56,26 +56,26 @@ pub struct Builder {
origins: Option<HashSet<HeaderValue>>,
}
impl Builder {
/// Sets whether to add the `Access-Control-Allow-Credentials` header.
pub fn allow_credentials(mut self, allow: bool) -> Self {
loop {}
}
/// Adds a method to the existing list of allowed request methods.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `http::Method`.
pub fn allow_method<M>(mut self, method: M) -> Self
where
http::Method: TryFrom<M>,
{
loop {}
}
/// Adds multiple methods to the existing list of allowed request methods.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `http::Method`.
pub fn allow_methods<I>(mut self, methods: I) -> Self
where
I: IntoIterator,
@ -83,26 +83,26 @@ impl Builder {
{
loop {}
}
/// Adds a header to the list of allowed request headers.
///
/// **Note**: These should match the values the browser sends via `Access-Control-Request-Headers`, e.g. `content-type`.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `http::header::HeaderName`.
pub fn allow_header<H>(mut self, header: H) -> Self
where
HeaderName: TryFrom<H>,
{
loop {}
}
/// Adds multiple headers to the list of allowed request headers.
///
/// **Note**: These should match the values the browser sends via `Access-Control-Request-Headers`, e.g.`content-type`.
///
/// # Panics
///
/// Panics if any of the headers are not a valid `http::header::HeaderName`.
pub fn allow_headers<I>(mut self, headers: I) -> Self
where
I: IntoIterator,
@ -110,22 +110,22 @@ impl Builder {
{
loop {}
}
/// Adds a header to the list of exposed headers.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `http::header::HeaderName`.
pub fn expose_header<H>(mut self, header: H) -> Self
where
HeaderName: TryFrom<H>,
{
loop {}
}
/// Adds multiple headers to the list of exposed headers.
///
/// # Panics
///
/// Panics if any of the headers are not a valid `http::header::HeaderName`.
pub fn expose_headers<I>(mut self, headers: I) -> Self
where
I: IntoIterator,
@ -133,28 +133,28 @@ impl Builder {
{
loop {}
}
/// Sets that *any* `Origin` header is allowed.
///
/// # Warning
///
/// This can allow websites you didn't intend to access this resource,
/// it is usually better to set an explicit list.
pub fn allow_any_origin(mut self) -> Self {
loop {}
}
/// Add an origin to the existing list of allowed `Origin`s.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `Origin`.
pub fn allow_origin(self, origin: impl IntoOrigin) -> Self {
loop {}
}
/// Add multiple origins to the existing list of allowed `Origin`s.
///
/// # Panics
///
/// Panics if the provided argument is not a valid `Origin`.
pub fn allow_origins<I>(mut self, origins: I) -> Self
where
I: IntoIterator,
@ -162,27 +162,27 @@ impl Builder {
{
loop {}
}
/// Sets the `Access-Control-Max-Age` header.
///
/// # Example
///
///
/// ```
/// use std::time::Duration;
/// use warp::Filter;
///
/// let cors = warp::cors()
/// .max_age(30) // 30u32 seconds
/// .max_age(Duration::from_secs(30)); // or a Duration
/// ```
pub fn max_age(mut self, seconds: impl Seconds) -> Self {
loop {}
}
/// Builds the `Cors` wrapper from the configured settings.
///
/// This step isn't *required*, as the `Builder` itself can be passed
/// to `Filter::with`. This just allows constructing once, thus not needing
/// to pay the cost of "building" every time.
pub fn build(self) -> Cors {
loop {}
}
@ -211,7 +211,7 @@ where
loop {}
}
}
/// An error used to reject requests that are forbidden by a `cors` filter.
pub struct CorsForbidden {
kind: Forbidden,
}

View file

@ -7,9 +7,9 @@ use futures_util::future;
use crate::filter::{filter_fn_one, Filter};
use crate::reject::{self, Rejection};
/// Get a previously set extension of the current route.
///
/// If the extension doesn't exist, this rejects with a `MissingExtension`.
pub fn get<T: Clone + Send + Sync + 'static>(
) -> impl Filter<Extract = (T,), Error = Rejection> + Copy {
filter_fn_one(|route| {
@ -22,15 +22,15 @@ pub fn get<T: Clone + Send + Sync + 'static>(
})
}
/// Get a previously set extension of the current route.
///
/// If the extension doesn't exist, it yields `None`.
pub fn optional<T: Clone + Send + Sync + 'static>(
) -> impl Filter<Extract = (Option<T>,), Error = Infallible> + Copy {
filter_fn_one(|route| future::ok(route.extensions().get::<T>().cloned()))
}
unit_error! {
/// An error used to reject if `get` cannot find the extension.
pub MissingExtension: "Missing request extension"
}

View file

@ -25,22 +25,22 @@ use tokio_util::io::poll_read_buf;
use crate::filter::{Filter, FilterClone, One};
use crate::reject::{self, Rejection};
use crate::reply::{Reply, Response};
/// Creates a `Filter` that serves a File at the `path`.
///
/// Does not filter out based on any information of the request. Always serves
/// the file at the exact `path` provided. Thus, this can be used to serve a
/// single file with `GET`s, but could also be used in combination with other
/// filters, such as after validating in `POST` request, wanting to return a
/// specific file as the body.
///
/// For serving a directory, see [dir](dir).
///
/// # Example
///
/// ```
/// // Always serves this file from the file system.
/// let route = warp::fs::file("/www/static/app.js");
/// ```
pub fn file(
path: impl Into<PathBuf>,
) -> impl FilterClone<Extract = One<File>, Error = Rejection> {
@ -53,28 +53,28 @@ pub fn file(
.and(conditionals())
.and_then(file_reply)
}
/// Creates a `Filter` that serves a directory at the base `path` joined
/// by the request path.
///
/// This can be used to serve "static files" from a directory. By far the most
/// common pattern of serving static files is for `GET` requests, so this
/// filter automatically includes a `GET` check.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Matches requests that start with `/static`,
/// // and then uses the rest of that path to lookup
/// // and serve a file from `/www/static`.
/// let route = warp::path("static")
/// .and(warp::fs::dir("/www/static"));
///
/// // For example:
/// // - `GET /static/app.js` would serve the file `/www/static/app.js`
/// // - `GET /static/css/app.css` would serve the file `/www/static/css/app.css`
/// ```
pub fn dir(
path: impl Into<PathBuf>,
) -> impl FilterClone<Extract = One<File>, Error = Rejection> {
@ -140,32 +140,32 @@ fn conditionals() -> impl Filter<
range,
})
}
/// A file response.
#[derive(Debug)]
pub struct File {
resp: Response,
path: ArcPath,
}
impl File {
/// Extract the `&Path` of the file this `Response` delivers.
///
/// # Example
///
/// The example below changes the Content-Type response header for every file called `video.mp4`.
///
/// ```
/// use warp::{Filter, reply::Reply};
///
/// let route = warp::path("static")
/// .and(warp::fs::dir("/www/static"))
/// .map(|reply: warp::filters::fs::File| {
/// if reply.path().ends_with("video.mp4") {
/// warp::reply::with_header(reply, "Content-Type", "video/mp4").into_response()
/// } else {
/// reply.into_response()
/// }
/// });
/// ```
pub fn path(&self) -> &Path {
loop {}
}

View file

@ -15,25 +15,25 @@ use http::HeaderMap;
use crate::filter::{filter_fn, filter_fn_one, Filter, One};
use crate::reject::{self, Rejection};
/// Create a `Filter` that tries to parse the specified header.
///
/// This `Filter` will look for a header with supplied name, and try to
/// parse to a `T`, otherwise rejects the request.
///
/// # Example
///
/// ```
/// use std::net::SocketAddr;
///
/// // Parse `content-length: 100` as a `u64`
/// let content_length = warp::header::<u64>("content-length");
///
/// // Parse `host: 127.0.0.1:8080` as a `SocketAddr
/// let local_host = warp::header::<SocketAddr>("host");
///
/// // Parse `foo: bar` into a `String`
/// let foo = warp::header::<String>("foo");
/// ```
pub fn header<T: FromStr + Send + 'static>(
name: &'static str,
) -> impl Filter<Extract = One<T>, Error = Rejection> + Copy {
@ -61,18 +61,18 @@ pub(crate) fn header2<T: Header + Send + 'static>(
})
}
/// Create a `Filter` that tries to parse the specified header, if it exists.
///
/// If the header does not exist, it yields `None`. Otherwise, it will try to
/// parse as a `T`, and if it fails, a invalid header rejection is return. If
/// successful, the filter yields `Some(T)`.
///
/// # Example
///
/// ```
/// // Grab the `authorization` header if it exists.
/// let opt_auth = warp::header::optional::<String>("authorization");
/// ```
pub fn optional<T>(
name: &'static str,
) -> impl Filter<Extract = One<Option<T>>, Error = Rejection> + Copy
@ -123,17 +123,17 @@ where
}
*/
/// Create a `Filter` that requires a header to match the value exactly.
///
/// This `Filter` will look for a header with supplied name and the exact
/// value, otherwise rejects the request.
///
/// # Example
///
/// ```
/// // Require `dnt: 1` header to be set.
/// let must_dnt = warp::header::exact("dnt", "1");
/// ```
pub fn exact(
name: &'static str,
value: &'static str,
@ -155,17 +155,17 @@ pub fn exact(
})
}
/// Create a `Filter` that requires a header to match the value exactly.
///
/// This `Filter` will look for a header with supplied name and the exact
/// value, ignoring ASCII case, otherwise rejects the request.
///
/// # Example
///
/// ```
/// // Require `connection: keep-alive` header to be set.
/// let keep_alive = warp::header::exact_ignore_case("connection", "keep-alive");
/// ```
pub fn exact_ignore_case(
name: &'static str,
value: &'static str,
@ -187,18 +187,18 @@ pub fn exact_ignore_case(
})
}
/// Create a `Filter` that gets a `HeaderValue` for the name.
///
/// # Example
///
/// ```
/// use warp::{Filter, http::header::HeaderValue};
///
/// let filter = warp::header::value("x-token")
/// .map(|value: HeaderValue| {
/// format!("header value bytes: {:?}", value)
/// });
/// ```
pub fn value(
name: &'static str,
) -> impl Filter<Extract = One<HeaderValue>, Error = Rejection> + Copy {
@ -213,18 +213,18 @@ pub fn value(
})
}
/// Create a `Filter` that returns a clone of the request's `HeaderMap`.
///
/// # Example
///
/// ```
/// use warp::{Filter, http::HeaderMap};
///
/// let headers = warp::header::headers_cloned()
/// .map(|headers: HeaderMap| {
/// format!("header count: {}", headers.len())
/// });
/// ```
pub fn headers_cloned() -> impl Filter<Extract = One<HeaderMap>, Error = Infallible> + Copy {
filter_fn_one(|route| future::ok(route.headers().clone()))
}

View file

@ -6,20 +6,20 @@ use futures_util::future;
pub use http::uri::Authority;
use std::str::FromStr;
/// Creates a `Filter` that requires a specific authority (target server's
/// host and port) in the request.
///
/// Authority is specified either in the `Host` header or in the target URI.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let multihost =
/// warp::host::exact("foo.com").map(|| "you've reached foo.com")
/// .or(warp::host::exact("bar.com").map(|| "you've reached bar.com"));
/// ```
pub fn exact(expected: &str) -> impl Filter<Extract = (), Error = Rejection> + Clone {
let expected = Authority::from_str(expected).expect("invalid host/authority");
optional()
@ -30,31 +30,31 @@ pub fn exact(expected: &str) -> impl Filter<Extract = (), Error = Rejection> + C
.untuple_one()
}
/// Creates a `Filter` that looks for an authority (target server's host
/// and port) in the request.
///
/// Authority is specified either in the `Host` header or in the target URI.
///
/// If found, extracts the `Authority`, otherwise continues the request,
/// extracting `None`.
///
/// Rejects with `400 Bad Request` if the `Host` header is malformed or if there
/// is a mismatch between the `Host` header and the target URI.
///
/// # Example
///
/// ```
/// use warp::{Filter, host::Authority};
///
/// let host = warp::host::optional()
/// .map(|authority: Option<Authority>| {
/// if let Some(a) = authority {
/// format!("{} is currently not at home", a.host())
/// } else {
/// "please state who you're trying to reach".to_owned()
/// }
/// });
/// ```
pub fn optional() -> impl Filter<Extract = One<Option<Authority>>, Error = Rejection> + Copy {
filter_fn_one(move |route| {
// The authority can be sent by clients in various ways:

View file

@ -8,23 +8,23 @@ use crate::reject::IsReject;
use crate::reply::Reply;
use crate::route::Route;
use self::internal::WithLog;
/// Create a wrapping filter with the specified `name` as the `target`.
///
/// This uses the default access logging format, and log records produced
/// will have their `target` set to `name`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // If using something like `pretty_env_logger`,
/// // view logs by setting `RUST_LOG=example::api`.
/// let log = warp::log("example::api");
/// let route = warp::any()
/// .map(warp::reply)
/// .with(log);
/// ```
pub fn log(name: &'static str) -> Log<impl Fn(Info<'_>) + Copy> {
let func = move |info: Info<'_>| {
log::info!(
@ -36,38 +36,38 @@ pub fn log(name: &'static str) -> Log<impl Fn(Info<'_>) + Copy> {
};
Log { func }
}
/// Create a wrapping filter that receives `warp::log::Info`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let log = warp::log::custom(|info| {
/// // Use a log macro, or slog, or println, or whatever!
/// eprintln!(
/// "{} {} {}",
/// info.method(),
/// info.path(),
/// info.status(),
/// );
/// });
/// let route = warp::any()
/// .map(warp::reply)
/// .with(log);
/// ```
pub fn custom<F>(func: F) -> Log<F>
where
F: Fn(Info<'_>),
{
loop {}
}
/// Decorates a [`Filter`](crate::Filter) to log requests and responses.
#[derive(Clone, Copy, Debug)]
pub struct Log<F> {
func: F,
}
/// Information about the request/response that can be used to prepare log lines.
#[allow(missing_debug_implementations)]
pub struct Info<'a> {
route: &'a Route,
@ -87,43 +87,43 @@ where
}
}
impl<'a> Info<'a> {
/// View the remote `SocketAddr` of the request.
pub fn remote_addr(&self) -> Option<SocketAddr> {
loop {}
}
/// View the `http::Method` of the request.
pub fn method(&self) -> &http::Method {
loop {}
}
/// View the URI path of the request.
pub fn path(&self) -> &str {
loop {}
}
/// View the `http::Version` of the request.
pub fn version(&self) -> http::Version {
loop {}
}
/// View the `http::StatusCode` of the response.
pub fn status(&self) -> http::StatusCode {
loop {}
}
/// View the referer of the request.
pub fn referer(&self) -> Option<&str> {
loop {}
}
/// View the user agent of the request.
pub fn user_agent(&self) -> Option<&str> {
loop {}
}
/// View the `Duration` that elapsed for the request.
pub fn elapsed(&self) -> Duration {
loop {}
}
/// View the host of the request
pub fn host(&self) -> Option<&str> {
loop {}
}
/// Access the full headers of the request
pub fn request_headers(&self) -> &http::HeaderMap {
loop {}
}

View file

@ -11,104 +11,104 @@ use http::Method;
use crate::filter::{filter_fn, filter_fn_one, Filter, One};
use crate::reject::Rejection;
use std::convert::Infallible;
/// Create a `Filter` that requires the request method to be `GET`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let get_only = warp::get().map(warp::reply);
/// ```
pub fn get() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::GET)
}
/// Create a `Filter` that requires the request method to be `POST`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let post_only = warp::post().map(warp::reply);
/// ```
pub fn post() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::POST)
}
/// Create a `Filter` that requires the request method to be `PUT`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let put_only = warp::put().map(warp::reply);
/// ```
pub fn put() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::PUT)
}
/// Create a `Filter` that requires the request method to be `DELETE`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let delete_only = warp::delete().map(warp::reply);
/// ```
pub fn delete() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::DELETE)
}
/// Create a `Filter` that requires the request method to be `HEAD`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let head_only = warp::head().map(warp::reply);
/// ```
pub fn head() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::HEAD)
}
/// Create a `Filter` that requires the request method to be `OPTIONS`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let options_only = warp::options().map(warp::reply);
/// ```
pub fn options() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::OPTIONS)
}
/// Create a `Filter` that requires the request method to be `PATCH`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let patch_only = warp::patch().map(warp::reply);
/// ```
pub fn patch() -> impl Filter<Extract = (), Error = Rejection> + Copy {
method_is(|| &Method::PATCH)
}
/// Extract the `Method` from the request.
///
/// This never rejects a request.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::method()
/// .map(|method| {
/// format!("You sent a {} request!", method)
/// });
/// ```
pub fn method() -> impl Filter<Extract = One<Method>, Error = Infallible> + Copy {
filter_fn_one(|route| future::ok::<_, Infallible>(route.method().clone()))
}

View file

@ -14,39 +14,39 @@ use multipart::server::Multipart;
use crate::filter::{Filter, FilterBase, Internal};
use crate::reject::{self, Rejection};
const DEFAULT_FORM_DATA_MAX_LENGTH: u64 = 1024 * 1024 * 2;
/// A `Filter` to extract a `multipart/form-data` body from a request.
///
/// Create with the `warp::multipart::form()` function.
#[derive(Debug, Clone)]
pub struct FormOptions {
max_length: u64,
}
/// A `Stream` of multipart/form-data `Part`s.
///
/// Extracted with a `warp::multipart::form` filter.
pub struct FormData {
inner: Multipart<Cursor<::bytes::Bytes>>,
}
/// A single "part" of a multipart/form-data body.
///
/// Yielded from the `FormData` stream.
pub struct Part {
name: String,
filename: Option<String>,
content_type: Option<String>,
data: Option<Vec<u8>>,
}
/// Create a `Filter` to extract a `multipart/form-data` body from a request.
///
/// The extracted `FormData` type is a `Stream` of `Part`s, and each `Part`
/// in turn is a `Stream` of bytes.
pub fn form() -> FormOptions {
loop {}
}
impl FormOptions {
/// Set the maximum byte length allowed for this body.
///
/// Defaults to 2MB.
pub fn max_length(mut self, max: u64) -> Self {
loop {}
}
@ -75,23 +75,23 @@ impl Stream for FormData {
}
}
impl Part {
/// Get the name of this part.
pub fn name(&self) -> &str {
loop {}
}
/// Get the filename of this part, if present.
pub fn filename(&self) -> Option<&str> {
loop {}
}
/// Get the content-type of this part, if present.
pub fn content_type(&self) -> Option<&str> {
loop {}
}
/// Asynchronously get some of the data for this `Part`.
pub async fn data(&mut self) -> Option<Result<impl Buf, crate::Error>> {
loop {}
}
/// Convert this `Part` into a `Stream` of `Buf`s.
pub fn stream(self) -> impl Stream<Item = Result<impl Buf, crate::Error>> {
loop {}
}

View file

@ -133,42 +133,42 @@ use self::internal::Opaque;
use crate::filter::{filter_fn, one, Filter, FilterBase, Internal, One, Tuple};
use crate::reject::{self, Rejection};
use crate::route::Route;
/// Create an exact match path segment `Filter`.
///
/// This will try to match exactly to the current request path segment.
///
/// # Note
///
/// - [`end()`](./fn.end.html) should be used to match the end of a path to avoid having
/// filters for shorter paths like `/math` unintentionally match a longer
/// path such as `/math/sum`
/// - Path-related filters should generally come **before** other types of filters, such
/// as those checking headers or body types. Including those other filters before
/// the path checks may result in strange errors being returned because a given request
/// does not match the parameters for a completely separate route.
///
/// # Panics
///
/// Exact path filters cannot be empty, or contain slashes.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Matches '/hello'
/// let hello = warp::path("hello")
/// .map(|| "Hello, World!");
/// ```
pub fn path<P>(p: P) -> Exact<Opaque<P>>
where
P: AsRef<str>,
{
loop {}
}
/// A `Filter` matching an exact path segment.
///
/// Constructed from `path()` or `path!()`.
#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
pub struct Exact<P>(P);
@ -184,20 +184,20 @@ where
loop {}
}
}
/// Matches the end of a route.
///
/// Note that _not_ including `end()` may result in shorter paths like
/// `/math` unintentionally matching `/math/sum`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Matches '/'
/// let hello = warp::path::end()
/// .map(|| "Hello, World!");
/// ```
pub fn end() -> impl Filter<Extract = (), Error = Rejection> + Copy {
filter_fn(move |route| {
if route.path().is_empty() {
@ -207,24 +207,24 @@ pub fn end() -> impl Filter<Extract = (), Error = Rejection> + Copy {
}
})
}
/// Extract a parameter from a path segment.
///
/// This will try to parse a value from the current request path
/// segment, and if successful, the value is returned as the `Filter`'s
/// "extracted" value.
///
/// If the value could not be parsed, rejects with a `404 Not Found`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::path::param()
/// .map(|id: u32| {
/// format!("You asked for /{}", id)
/// });
/// ```
pub fn param<T: FromStr + Send + 'static>() -> impl Filter<
Extract = One<T>,
Error = Rejection,
@ -237,23 +237,23 @@ pub fn param<T: FromStr + Send + 'static>() -> impl Filter<
T::from_str(seg).map(one).map_err(|_| reject::not_found())
})
}
/// Extract the unmatched tail of the path.
///
/// This will return a `Tail`, which allows access to the rest of the path
/// that previous filters have not already matched.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::path("foo")
/// .and(warp::path::tail())
/// .map(|tail| {
/// // GET /foo/bar/baz would return "bar/baz".
/// format!("The tail after foo is {:?}", tail)
/// });
/// ```
pub fn tail() -> impl Filter<Extract = One<Tail>, Error = Infallible> + Copy {
filter_fn(move |route| {
let path = path_and_query(route);
@ -263,13 +263,13 @@ pub fn tail() -> impl Filter<Extract = One<Tail>, Error = Infallible> + Copy {
future::ok(one(Tail { path, start_index: idx }))
})
}
/// Represents the tail part of a request path, returned by the [`tail()`] filter.
pub struct Tail {
path: PathAndQuery,
start_index: usize,
}
impl Tail {
/// Get the `&str` representation of the remaining path.
pub fn as_str(&self) -> &str {
loop {}
}
@ -279,24 +279,24 @@ impl fmt::Debug for Tail {
loop {}
}
}
/// Peek at the unmatched tail of the path, without affecting the matched path.
///
/// This will return a `Peek`, which allows access to the rest of the path
/// that previous filters have not already matched. This differs from `tail`
/// in that `peek` will **not** set the entire path as matched.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::path("foo")
/// .and(warp::path::peek())
/// .map(|peek| {
/// // GET /foo/bar/baz would return "bar/baz".
/// format!("The path after foo is {:?}", peek)
/// });
/// ```
pub fn peek() -> impl Filter<Extract = One<Peek>, Error = Infallible> + Copy {
filter_fn(move |route| {
let path = path_and_query(route);
@ -304,17 +304,17 @@ pub fn peek() -> impl Filter<Extract = One<Peek>, Error = Infallible> + Copy {
future::ok(one(Peek { path, start_index: idx }))
})
}
/// Represents the tail part of a request path, returned by the [`peek()`] filter.
pub struct Peek {
path: PathAndQuery,
start_index: usize,
}
impl Peek {
/// Get the `&str` representation of the remaining path.
pub fn as_str(&self) -> &str {
loop {}
}
/// Get an iterator over the segments of the peeked path.
pub fn segments(&self) -> impl Iterator<Item = &str> {
self.as_str().split('/').filter(|seg| !seg.is_empty())
}
@ -324,44 +324,44 @@ impl fmt::Debug for Peek {
loop {}
}
}
/// Returns the full request path, irrespective of other filters.
///
/// This will return a `FullPath`, which can be stringified to return the
/// full path of the request.
///
/// This is more useful in generic pre/post-processing filters, and should
/// probably not be used for request matching/routing.
///
/// # Example
///
/// ```
/// use warp::{Filter, path::FullPath};
/// use std::{collections::HashMap, sync::{Arc, Mutex}};
///
/// let counts = Arc::new(Mutex::new(HashMap::new()));
/// let access_counter = warp::path::full()
/// .map(move |path: FullPath| {
/// let mut counts = counts.lock().unwrap();
///
/// *counts.entry(path.as_str().to_string())
/// .and_modify(|c| *c += 1)
/// .or_insert(0)
/// });
///
/// let route = warp::path("foo")
/// .and(warp::path("bar"))
/// .and(access_counter)
/// .map(|count| {
/// format!("This is the {}th visit to this URL!", count)
/// });
/// ```
pub fn full() -> impl Filter<Extract = One<FullPath>, Error = Infallible> + Copy {
filter_fn(move |route| future::ok(one(FullPath(path_and_query(route)))))
}
/// Represents the full request path, returned by the [`full()`] filter.
pub struct FullPath(PathAndQuery);
impl FullPath {
/// Get the `&str` representation of the request path.
pub fn as_str(&self) -> &str {
loop {}
}
@ -387,61 +387,61 @@ where
fn path_and_query(route: &Route) -> PathAndQuery {
loop {}
}
/// Convenient way to chain multiple path filters together.
///
/// Any number of either type identifiers or string expressions can be passed,
/// each separated by a forward slash (`/`). Strings will be used to match
/// path segments exactly, and type identifiers are used just like
/// [`param`](crate::path::param) filters.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Match `/sum/:a/:b`
/// let route = warp::path!("sum" / u32 / u32)
/// .map(|a, b| {
/// format!("{} + {} = {}", a, b, a + b)
/// });
/// ```
///
/// The equivalent filter chain without using the `path!` macro looks this:
///
/// ```
/// use warp::Filter;
///
/// let route = warp::path("sum")
/// .and(warp::path::param::<u32>())
/// .and(warp::path::param::<u32>())
/// .and(warp::path::end())
/// .map(|a, b| {
/// format!("{} + {} = {}", a, b, a + b)
/// });
/// ```
///
/// # Path Prefixes
///
/// The `path!` macro automatically assumes the path should include an `end()`
/// filter. To build up a path filter *prefix*, such that the `end()` isn't
/// included, use the `/ ..` syntax.
///
///
/// ```
/// use warp::Filter;
///
/// let prefix = warp::path!("math" / "sum" / ..);
///
/// let sum = warp::path!(u32 / u32)
/// .map(|a, b| {
/// format!("{} + {} = {}", a, b, a + b)
/// });
///
/// let help = warp::path::end()
/// .map(|| "This API returns the sum of two u32's");
///
/// let api = prefix.and(sum.or(help));
/// ```
#[macro_export]
macro_rules! path {
($($pieces:tt)*) => {
@ -486,25 +486,25 @@ macro_rules! __internal_path {
$crate ::path(__StaticPath) }
};
}
/// ```compile_fail
/// warp::path!("foo" / .. / "bar");
/// ```
///
/// ```compile_fail
/// warp::path!(.. / "bar");
/// ```
///
/// ```compile_fail
/// warp::path!("foo" ..);
/// ```
///
/// ```compile_fail
/// warp::path!("foo" / .. /);
/// ```
///
/// ```compile_fail
/// warp::path!(..);
/// ```
fn _path_macro_compile_fail() {}
mod internal {
#[allow(missing_debug_implementations)]

View file

@ -7,61 +7,61 @@ use serde_urlencoded;
use crate::filter::{filter_fn_one, Filter, One};
use crate::reject::{self, Rejection};
/// Creates a `Filter` that decodes query parameters to the type `T`.
///
/// If cannot decode into a `T`, the request is rejected with a `400 Bad Request`.
///
/// # Example
///
/// ```
/// use std::collections::HashMap;
/// use warp::{
/// http::Response,
/// Filter,
/// };
///
/// let route = warp::any()
/// .and(warp::query::<HashMap<String, String>>())
/// .map(|map: HashMap<String, String>| {
/// let mut response: Vec<String> = Vec::new();
/// for (key, value) in map.into_iter() {
/// response.push(format!("{}={}", key, value))
/// }
/// Response::builder().body(response.join(";"))
/// });
/// ```
///
/// You can define your custom query object and deserialize with [Serde][Serde]. Ensure to include
/// the crate in your dependencies before usage.
///
/// ```
/// use serde_derive::{Deserialize, Serialize};
/// use std::collections::HashMap;
/// use warp::{
/// http::Response,
/// Filter,
/// };
///
/// #[derive(Serialize, Deserialize)]
/// struct FooQuery {
/// foo: Option<String>,
/// bar: u8,
/// }
///
/// let route = warp::any()
/// .and(warp::query::<FooQuery>())
/// .map(|q: FooQuery| {
/// if let Some(foo) = q.foo {
/// Response::builder().body(format!("foo={}", foo))
/// } else {
/// Response::builder().body(format!("bar={}", q.bar))
/// }
/// });
/// ```
///
/// For more examples, please take a look at [examples/query_string.rs](https://github.com/seanmonstar/warp/blob/master/examples/query_string.rs).
///
/// [Serde]: https://docs.rs/serde
pub fn query<T: DeserializeOwned + Send + 'static>(
) -> impl Filter<Extract = One<T>, Error = Rejection> + Copy {
filter_fn_one(|route| {
@ -78,7 +78,7 @@ pub fn query<T: DeserializeOwned + Send + 'static>(
})
}
/// Creates a `Filter` that returns the raw query string as type String.
pub fn raw() -> impl Filter<Extract = One<String>, Error = Rejection> + Copy {
filter_fn_one(|route| {
let route = route

View file

@ -24,24 +24,24 @@ use http::header::{HeaderMap, HeaderName, HeaderValue};
use self::sealed::{WithDefaultHeader_, WithHeader_, WithHeaders_};
use crate::filter::{Filter, Map, WrapSealed};
use crate::reply::Reply;
/// Wrap a [`Filter`](crate::Filter) that adds a header to the reply.
///
/// # Note
///
/// This **only** adds a header if the underlying filter is successful, and
/// returns a [`Reply`](Reply). If the underlying filter was rejected, the
/// header is not added.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Always set `foo: bar` header.
/// let route = warp::any()
/// .map(warp::reply)
/// .with(warp::reply::with::header("foo", "bar"));
/// ```
pub fn header<K, V>(name: K, value: V) -> WithHeader
where
HeaderName: TryFrom<K>,
@ -51,51 +51,51 @@ where
{
loop {}
}
/// Wrap a [`Filter`](crate::Filter) that adds multiple headers to the reply.
///
/// # Note
///
/// This **only** adds a header if the underlying filter is successful, and
/// returns a [`Reply`](Reply). If the underlying filter was rejected, the
/// header is not added.
///
/// # Example
///
/// ```
/// use warp::http::header::{HeaderMap, HeaderValue};
/// use warp::Filter;
///
/// let mut headers = HeaderMap::new();
/// headers.insert("server", HeaderValue::from_static("wee/0"));
/// headers.insert("foo", HeaderValue::from_static("bar"));
///
/// // Always set `server: wee/0` and `foo: bar` headers.
/// let route = warp::any()
/// .map(warp::reply)
/// .with(warp::reply::with::headers(headers));
/// ```
pub fn headers(headers: HeaderMap) -> WithHeaders {
loop {}
}
/// Wrap a [`Filter`](crate::Filter) that adds a header to the reply, if they
/// aren't already set.
///
/// # Note
///
/// This **only** adds a header if the underlying filter is successful, and
/// returns a [`Reply`](Reply). If the underlying filter was rejected, the
/// header is not added.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // Set `server: warp` if not already set.
/// let route = warp::any()
/// .map(warp::reply)
/// .with(warp::reply::with::default_header("server", "warp"));
/// ```
pub fn default_header<K, V>(name: K, value: V) -> WithDefaultHeader
where
HeaderName: TryFrom<K>,
@ -105,7 +105,7 @@ where
{
loop {}
}
/// Wrap a `Filter` to always set a header.
#[derive(Clone, Debug)]
pub struct WithHeader {
name: HeaderName,
@ -121,7 +121,7 @@ where
loop {}
}
}
/// Wrap a `Filter` to always set multiple headers.
#[derive(Clone, Debug)]
pub struct WithHeaders {
headers: Arc<HeaderMap>,
@ -136,7 +136,7 @@ where
loop {}
}
}
/// Wrap a `Filter` to set a header if it is not already set.
#[derive(Clone, Debug)]
pub struct WithDefaultHeader {
name: HeaderName,

View file

@ -63,7 +63,7 @@ enum DataType {
Text(String),
Json(String),
}
/// Server-sent event
#[derive(Default, Debug)]
pub struct Event {
id: Option<String>,
@ -73,33 +73,33 @@ pub struct Event {
retry: Option<Duration>,
}
impl Event {
/// Set Server-sent event data
/// data field(s) ("data:<content>")
pub fn data<T: Into<String>>(mut self, data: T) -> Event {
loop {}
}
/// Set Server-sent event data
/// data field(s) ("data:<content>")
pub fn json_data<T: Serialize>(mut self, data: T) -> Result<Event, Error> {
loop {}
}
/// Set Server-sent event comment
/// Comment field (":<comment-text>")
pub fn comment<T: Into<String>>(mut self, comment: T) -> Event {
loop {}
}
/// Set Server-sent event event
/// Event name field ("event:<event-name>")
pub fn event<T: Into<String>>(mut self, event: T) -> Event {
loop {}
}
/// Set Server-sent event retry
/// Retry timeout field ("retry:<timeout>")
pub fn retry(mut self, duration: Duration) -> Event {
loop {}
}
/// Set Server-sent event id
/// Identifier field ("id:<identifier>")
pub fn id<T: Into<String>>(mut self, id: T) -> Event {
loop {}
}
@ -109,42 +109,42 @@ impl fmt::Display for Event {
loop {}
}
}
/// Gets the optional last event id from request.
/// Typically this identifier represented as number or string.
///
/// ```
/// let app = warp::sse::last_event_id::<u32>();
///
/// // The identifier is present
/// async {
/// assert_eq!(
/// warp::test::request()
/// .header("Last-Event-ID", "12")
/// .filter(&app)
/// .await
/// .unwrap(),
/// Some(12)
/// );
///
/// // The identifier is missing
/// assert_eq!(
/// warp::test::request()
/// .filter(&app)
/// .await
/// .unwrap(),
/// None
/// );
///
/// // The identifier is not a valid
/// assert!(
/// warp::test::request()
/// .header("Last-Event-ID", "abc")
/// .filter(&app)
/// .await
/// .is_err(),
/// );
///};
/// ```
pub fn last_event_id<T>() -> impl Filter<
Extract = One<Option<T>>,
Error = Rejection,
@ -154,83 +154,83 @@ where
{
header::optional("last-event-id")
}
/// Server-sent events reply
///
/// This function converts stream of server events into a `Reply` with:
///
/// - Status of `200 OK`
/// - Header `content-type: text/event-stream`
/// - Header `cache-control: no-cache`.
///
/// # Example
///
/// ```
///
/// use std::time::Duration;
/// use futures_util::Stream;
/// use futures_util::stream::iter;
/// use std::convert::Infallible;
/// use warp::{Filter, sse::Event};
/// use serde_derive::Serialize;
///
/// #[derive(Serialize)]
/// struct Msg {
/// from: u32,
/// text: String,
/// }
///
/// fn event_stream() -> impl Stream<Item = Result<Event, Infallible>> {
/// iter(vec![
/// // Unnamed event with data only
/// Ok(Event::default().data("payload")),
/// // Named event with ID and retry timeout
/// Ok(
/// Event::default().data("other message\nwith next line")
/// .event("chat")
/// .id(1.to_string())
/// .retry(Duration::from_millis(15000))
/// ),
/// // Event with JSON data
/// Ok(
/// Event::default().id(2.to_string())
/// .json_data(Msg {
/// from: 2,
/// text: "hello".into(),
/// }).unwrap(),
/// )
/// ])
/// }
///
/// async {
/// let app = warp::path("sse").and(warp::get()).map(|| {
/// warp::sse::reply(event_stream())
/// });
///
/// let res = warp::test::request()
/// .method("GET")
/// .header("Connection", "Keep-Alive")
/// .path("/sse")
/// .reply(&app)
/// .await
/// .into_body();
///
/// assert_eq!(
/// res,
/// r#"data:payload
///
/// event:chat
/// data:other message
/// data:with next line
/// id:1
/// retry:15000
///
/// data:{"from":2,"text":"hello"}
/// id:2
///
/// "#
/// );
/// };
/// ```
pub fn reply<S>(event_stream: S) -> impl Reply
where
S: TryStream<Ok = Event> + Send + 'static,
@ -252,29 +252,29 @@ where
loop {}
}
}
/// Configure the interval between keep-alive messages, the content
/// of each message, and the associated stream.
#[derive(Debug)]
pub struct KeepAlive {
comment_text: Cow<'static, str>,
max_interval: Duration,
}
impl KeepAlive {
/// Customize the interval between keep-alive messages.
///
/// Default is 15 seconds.
pub fn interval(mut self, time: Duration) -> Self {
loop {}
}
/// Customize the text of the keep-alive message.
///
/// Default is an empty comment.
pub fn text(mut self, text: impl Into<Cow<'static, str>>) -> Self {
loop {}
}
/// Wrap an event stream with keep-alive functionality.
///
/// See [`keep_alive`](keep_alive) for more.
pub fn stream<S>(
self,
event_stream: S,
@ -305,51 +305,51 @@ struct SseKeepAlive<S> {
#[pin]
alive_timer: Sleep,
}
/// Keeps event source connection alive when no events sent over a some time.
///
/// Some proxy servers may drop HTTP connection after a some timeout of inactivity.
/// This function helps to prevent such behavior by sending comment events every
/// `keep_interval` of inactivity.
///
/// By default the comment is `:` (an empty comment) and the time interval between
/// events is 15 seconds. Both may be customized using the builder pattern
/// as shown below.
///
/// ```
/// use std::time::Duration;
/// use std::convert::Infallible;
/// use futures_util::StreamExt;
/// use tokio::time::interval;
/// use tokio_stream::wrappers::IntervalStream;
/// use warp::{Filter, Stream, sse::Event};
///
/// // create server-sent event
/// fn sse_counter(counter: u64) -> Result<Event, Infallible> {
/// Ok(Event::default().data(counter.to_string()))
/// }
///
/// fn main() {
/// let routes = warp::path("ticks")
/// .and(warp::get())
/// .map(|| {
/// let mut counter: u64 = 0;
/// let interval = interval(Duration::from_secs(15));
/// let stream = IntervalStream::new(interval);
/// let event_stream = stream.map(move |_| {
/// counter += 1;
/// sse_counter(counter)
/// });
/// // reply using server-sent events
/// let stream = warp::sse::keep_alive()
/// .interval(Duration::from_secs(5))
/// .text("thump".to_string())
/// .stream(event_stream);
/// warp::sse::reply(stream)
/// });
/// }
/// ```
///
/// See [notes](https://www.w3.org/TR/2009/WD-eventsource-20090421/#notes).
pub fn keep_alive() -> KeepAlive {
loop {}
}
@ -368,7 +368,7 @@ where
}
mod sealed {
use super::*;
/// SSE error type
#[derive(Debug)]
pub struct SseError;
impl fmt::Display for SseError {

View file

@ -16,94 +16,94 @@ use crate::reject::IsReject;
use crate::reply::Reply;
use crate::route::Route;
use self::internal::WithTrace;
/// Create a wrapping filter that instruments every request with a `tracing`
/// [`Span`] at the [`INFO`] level, containing a summary of the request.
/// Additionally, if the [`DEBUG`] level is enabled, the span will contain an
/// event recording the request's headers.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(warp::reply)
/// .with(warp::trace::request());
/// ```
///
/// [`Span`]: https://docs.rs/tracing/latest/tracing/#spans
/// [`INFO`]: https://docs.rs/tracing/0.1.16/tracing/struct.Level.html#associatedconstant.INFO
/// [`DEBUG`]: https://docs.rs/tracing/0.1.16/tracing/struct.Level.html#associatedconstant.DEBUG
pub fn request() -> Trace<impl Fn(Info<'_>) -> Span + Clone> {
trace(|info: Info<'_>| {
loop {}
})
}
/// Create a wrapping filter that instruments every request with a custom
/// `tracing` [`Span`] provided by a function.
///
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(warp::reply)
/// .with(warp::trace(|info| {
/// // Create a span using tracing macros
/// tracing::info_span!(
/// "request",
/// method = %info.method(),
/// path = %info.path(),
/// )
/// }));
/// ```
///
/// [`Span`]: https://docs.rs/tracing/latest/tracing/#spans
pub fn trace<F>(func: F) -> Trace<F>
where
F: Fn(Info<'_>) -> Span + Clone,
{
loop {}
}
/// Create a wrapping filter that instruments every request with a `tracing`
/// [`Span`] at the [`DEBUG`] level representing a named context.
///
/// This can be used to instrument multiple routes with their own sub-spans in a
/// per-request trace.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let hello = warp::path("hello")
/// .map(warp::reply)
/// .with(warp::trace::named("hello"));
///
/// let goodbye = warp::path("goodbye")
/// .map(warp::reply)
/// .with(warp::trace::named("goodbye"));
///
/// let routes = hello.or(goodbye);
/// ```
///
/// [`Span`]: https://docs.rs/tracing/latest/tracing/#spans
/// [`DEBUG`]: https://docs.rs/tracing/0.1.16/tracing/struct.Level.html#associatedconstant.DEBUG
pub fn named(name: &'static str) -> Trace<impl Fn(Info<'_>) -> Span + Copy> {
trace(move |_| tracing::debug_span!("context", "{}", name,))
}
/// Decorates a [`Filter`](crate::Filter) to create a [`tracing`] [span] for
/// requests and responses.
///
/// [`tracing`]: https://crates.io/crates/tracing
/// [span]: https://docs.rs/tracing/latest/tracing/#spans
#[derive(Clone, Copy, Debug)]
pub struct Trace<F> {
func: F,
}
/// Information about the request/response that can be used to prepare log lines.
#[allow(missing_debug_implementations)]
pub struct Info<'a> {
route: &'a Route,
@ -121,35 +121,35 @@ where
}
}
impl<'a> Info<'a> {
/// View the remote `SocketAddr` of the request.
pub fn remote_addr(&self) -> Option<SocketAddr> {
loop {}
}
/// View the `http::Method` of the request.
pub fn method(&self) -> &http::Method {
loop {}
}
/// View the URI path of the request.
pub fn path(&self) -> &str {
loop {}
}
/// View the `http::Version` of the request.
pub fn version(&self) -> http::Version {
loop {}
}
/// View the referer of the request.
pub fn referer(&self) -> Option<&str> {
loop {}
}
/// View the user agent of the request.
pub fn user_agent(&self) -> Option<&str> {
loop {}
}
/// View the host of the request
pub fn host(&self) -> Option<&str> {
loop {}
}
/// View the request headers.
pub fn request_headers(&self) -> &http::HeaderMap {
loop {}
}

View file

@ -16,40 +16,40 @@ use tokio_tungstenite::{
tungstenite::protocol::{self, WebSocketConfig},
WebSocketStream,
};
/// Creates a Websocket Filter.
///
/// The yielded `Ws` is used to finish the websocket upgrade.
///
/// # Note
///
/// This filter combines multiple filters internally, so you don't need them:
///
/// - Method must be `GET`
/// - Header `connection` must be `upgrade`
/// - Header `upgrade` must be `websocket`
/// - Header `sec-websocket-version` must be `13`
/// - Header `sec-websocket-key` must be set.
///
/// If the filters are met, yields a `Ws`. Calling `Ws::on_upgrade` will
/// return a reply with:
///
/// - Status of `101 Switching Protocols`
/// - Header `connection: upgrade`
/// - Header `upgrade: websocket`
/// - Header `sec-websocket-accept` with the hash value of the received key.
pub fn ws() -> impl Filter<Extract = One<Ws>, Error = Rejection> + Copy {
loop {}
}
/// Extracted by the [`ws`](ws) filter, and used to finish an upgrade.
pub struct Ws {
config: Option<WebSocketConfig>,
key: SecWebsocketKey,
on_upgrade: Option<OnUpgrade>,
}
impl Ws {
/// Finish the upgrade, passing a function to handle the `WebSocket`.
///
/// The passed function must return a `Future`.
pub fn on_upgrade<F, U>(self, func: F) -> impl Reply
where
F: FnOnce(WebSocket) -> U + Send + 'static,
@ -57,15 +57,15 @@ impl Ws {
{
loop {}
}
/// Set the size of the internal message send queue.
pub fn max_send_queue(mut self, max: usize) -> Self {
loop {}
}
/// Set the maximum message size (defaults to 64 megabytes)
pub fn max_message_size(mut self, max: usize) -> Self {
loop {}
}
/// Set the maximum frame size (defaults to 16 megabytes)
pub fn max_frame_size(mut self, max: usize) -> Self {
loop {}
}
@ -95,14 +95,14 @@ fn on_upgrade() -> impl Filter<
> + Copy {
loop {}
}
/// A websocket `Stream` and `Sink`, provided to `ws` filters.
///
/// Ping messages sent from the client will be handled internally by replying with a Pong message.
/// Close messages need to be handled explicitly: usually by closing the `Sink` end of the
/// `WebSocket`.
///
/// **Note!**
/// Due to rust futures nature, pings won't be handled until read part of `WebSocket` is polled
pub struct WebSocket {
inner: WebSocketStream<hyper::upgrade::Upgraded>,
}
@ -114,7 +114,7 @@ impl WebSocket {
) -> Self {
loop {}
}
/// Gracefully close this websocket.
pub async fn close(mut self) -> Result<(), crate::Error> {
loop {}
}
@ -157,79 +157,79 @@ impl fmt::Debug for WebSocket {
loop {}
}
}
/// A WebSocket message.
///
/// This will likely become a `non-exhaustive` enum in the future, once that
/// language feature has stabilized.
#[derive(Eq, PartialEq, Clone)]
pub struct Message {
inner: protocol::Message,
}
impl Message {
/// Construct a new Text `Message`.
pub fn text<S: Into<String>>(s: S) -> Message {
loop {}
}
/// Construct a new Binary `Message`.
pub fn binary<V: Into<Vec<u8>>>(v: V) -> Message {
loop {}
}
/// Construct a new Ping `Message`.
pub fn ping<V: Into<Vec<u8>>>(v: V) -> Message {
loop {}
}
/// Construct a new Pong `Message`.
///
/// Note that one rarely needs to manually construct a Pong message because the underlying tungstenite socket
/// automatically responds to the Ping messages it receives. Manual construction might still be useful in some cases
/// like in tests or to send unidirectional heartbeats.
pub fn pong<V: Into<Vec<u8>>>(v: V) -> Message {
loop {}
}
/// Construct the default Close `Message`.
pub fn close() -> Message {
loop {}
}
/// Construct a Close `Message` with a code and reason.
pub fn close_with(
code: impl Into<u16>,
reason: impl Into<Cow<'static, str>>,
) -> Message {
loop {}
}
/// Returns true if this message is a Text message.
pub fn is_text(&self) -> bool {
loop {}
}
/// Returns true if this message is a Binary message.
pub fn is_binary(&self) -> bool {
loop {}
}
/// Returns true if this message a is a Close message.
pub fn is_close(&self) -> bool {
loop {}
}
/// Returns true if this message is a Ping message.
pub fn is_ping(&self) -> bool {
loop {}
}
/// Returns true if this message is a Pong message.
pub fn is_pong(&self) -> bool {
loop {}
}
/// Try to get the close frame (close code and reason)
pub fn close_frame(&self) -> Option<(u16, &str)> {
loop {}
}
/// Try to get a reference to the string text, if this is a Text message.
pub fn to_str(&self) -> Result<&str, ()> {
loop {}
}
/// Return the bytes of this message, if the message can contain data.
pub fn as_bytes(&self) -> &[u8] {
loop {}
}
/// Destructure this message into binary data.
pub fn into_bytes(self) -> Vec<u8> {
loop {}
}
@ -244,7 +244,7 @@ impl From<Message> for Vec<u8> {
loop {}
}
}
/// Connection header did not include 'upgrade'
#[derive(Debug)]
pub struct MissingConnectionUpgrade;
impl fmt::Display for MissingConnectionUpgrade {

View file

@ -5,18 +5,18 @@
use http::{header, StatusCode};
pub use self::sealed::AsLocation;
use crate::reply::{self, Reply};
/// A simple `301` permanent redirect to a different location.
///
/// # Example
///
/// ```
/// use warp::{http::Uri, Filter};
///
/// let route = warp::path("v1")
/// .map(|| {
/// warp::redirect(Uri::from_static("/v2"))
/// });
/// ```
pub fn redirect(uri: impl AsLocation) -> impl Reply {
reply::with_header(
StatusCode::MOVED_PERMANENTLY,
@ -24,53 +24,53 @@ pub fn redirect(uri: impl AsLocation) -> impl Reply {
uri.header_value(),
)
}
/// A simple `302` found redirect to a different location
///
/// # Example
///
/// ```
/// use warp::{http::Uri, Filter};
///
/// let route = warp::path("v1")
/// .map(|| {
/// warp::redirect::found(Uri::from_static("/v2"))
/// });
/// ```
pub fn found(uri: impl AsLocation) -> impl Reply {
reply::with_header(StatusCode::FOUND, header::LOCATION, uri.header_value())
}
/// A simple `303` redirect to a different location.
///
/// The HTTP method of the request to the new location will always be `GET`.
///
/// # Example
///
/// ```
/// use warp::{http::Uri, Filter};
///
/// let route = warp::path("v1")
/// .map(|| {
/// warp::redirect::see_other(Uri::from_static("/v2"))
/// });
/// ```
pub fn see_other(uri: impl AsLocation) -> impl Reply {
reply::with_header(StatusCode::SEE_OTHER, header::LOCATION, uri.header_value())
}
/// A simple `307` temporary redirect to a different location.
///
/// This is similar to [`see_other`](fn@see_other) but the HTTP method and the body of the request
/// to the new location will be the same as the method and body of the current request.
///
/// # Example
///
/// ```
/// use warp::{http::Uri, Filter};
///
/// let route = warp::path("v1")
/// .map(|| {
/// warp::redirect::temporary(Uri::from_static("/v2"))
/// });
/// ```
pub fn temporary(uri: impl AsLocation) -> impl Reply {
reply::with_header(
StatusCode::TEMPORARY_REDIRECT,
@ -78,21 +78,21 @@ pub fn temporary(uri: impl AsLocation) -> impl Reply {
uri.header_value(),
)
}
/// A simple `308` permanent redirect to a different location.
///
/// This is similar to [`redirect`](fn@redirect) but the HTTP method of the request to the new
/// location will be the same as the method of the current request.
///
/// # Example
///
/// ```
/// use warp::{http::Uri, Filter};
///
/// let route = warp::path("v1")
/// .map(|| {
/// warp::redirect::permanent(Uri::from_static("/v2"))
/// });
/// ```
pub fn permanent(uri: impl AsLocation) -> impl Reply {
reply::with_header(
StatusCode::PERMANENT_REDIRECT,
@ -103,10 +103,10 @@ pub fn permanent(uri: impl AsLocation) -> impl Reply {
mod sealed {
use http::{header::HeaderValue, Uri};
/// Trait for redirect locations. Currently only a `Uri` can be used in
/// redirect.
/// This sealed trait exists to allow adding possibly new impls so other
/// arguments could be accepted, like maybe just `warp::redirect("/v2")`.
pub trait AsLocation: Sealed {}
pub trait Sealed {
fn header_value(self) -> HeaderValue;

View file

@ -61,12 +61,12 @@ use std::error::Error as StdError;
use std::fmt;
use http::{self, StatusCode};
pub(crate) use self::sealed::{CombineRejection, IsReject};
/// Rejects a request with `404 Not Found`.
#[inline]
pub fn reject() -> Rejection {
loop {}
}
/// Rejects a request with `404 Not Found`.
#[inline]
pub fn not_found() -> Rejection {
loop {}
@ -103,41 +103,41 @@ pub(crate) fn payload_too_large() -> Rejection {
pub(crate) fn unsupported_media_type() -> Rejection {
loop {}
}
/// Rejects a request with a custom cause.
///
/// A [`recover`][] filter should convert this `Rejection` into a `Reply`,
/// or else this will be returned as a `500 Internal Server Error`.
///
/// [`recover`]: ../trait.Filter.html#method.recover
pub fn custom<T: Reject>(err: T) -> Rejection {
loop {}
}
/// Protect against re-rejecting a rejection.
///
/// ```compile_fail
/// fn with(r: warp::Rejection) {
/// let _wat = warp::reject::custom(r);
/// }
/// ```
fn __reject_custom_compilefail() {}
/// A marker trait to ensure proper types are used for custom rejections.
///
/// Can be converted into Rejection.
///
/// # Example
///
/// ```
/// use warp::{Filter, reject::Reject};
///
/// #[derive(Debug)]
/// struct RateLimited;
///
/// impl Reject for RateLimited {}
///
/// let route = warp::any().and_then(|| async {
/// Err::<(), _>(warp::reject::custom(RateLimited))
/// });
/// ```
pub trait Reject: fmt::Debug + Sized + Send + Sync + 'static {}
trait Cause: fmt::Debug + Send + Sync + 'static {
fn as_any(&self) -> &dyn Any;
@ -154,9 +154,9 @@ impl dyn Cause {}
pub(crate) fn known<T: Into<Known>>(err: T) -> Rejection {
loop {}
}
/// Rejection of a request by a [`Filter`](crate::Filter).
///
/// See the [`reject`](module@crate::reject) documentation for more.
pub struct Rejection {
reason: Reason,
}
@ -194,37 +194,37 @@ enum_known! {
BodyConsumedMultipleTimes(crate ::body::BodyConsumedMultipleTimes),
}
impl Rejection {
/// Searches this `Rejection` for a specific cause.
///
/// A `Rejection` will accumulate causes over a `Filter` chain. This method
/// can search through them and return the first cause of this type.
///
/// # Example
///
/// ```
/// #[derive(Debug)]
/// struct Nope;
///
/// impl warp::reject::Reject for Nope {}
///
/// let reject = warp::reject::custom(Nope);
///
/// if let Some(nope) = reject.find::<Nope>() {
/// println!("found it: {:?}", nope);
/// }
/// ```
pub fn find<T: 'static>(&self) -> Option<&T> {
loop {}
}
/// Returns true if this Rejection was made via `warp::reject::not_found`.
///
/// # Example
///
/// ```
/// let rejection = warp::reject();
///
/// assert!(rejection.is_not_found());
/// ```
pub fn is_not_found(&self) -> bool {
loop {}
}
@ -286,13 +286,13 @@ unit_error! {
#[doc = " The request's content-type is not supported"] pub UnsupportedMediaType :
"The request's content-type is not supported"
}
/// Missing request header
#[derive(Debug)]
pub struct MissingHeader {
name: &'static str,
}
impl MissingHeader {
/// Retrieve the name of the header that was missing
pub fn name(&self) -> &str {
loop {}
}
@ -303,13 +303,13 @@ impl fmt::Display for MissingHeader {
}
}
impl StdError for MissingHeader {}
/// Invalid request header
#[derive(Debug)]
pub struct InvalidHeader {
name: &'static str,
}
impl InvalidHeader {
/// Retrieve the name of the header that was invalid
pub fn name(&self) -> &str {
loop {}
}
@ -320,13 +320,13 @@ impl fmt::Display for InvalidHeader {
}
}
impl StdError for InvalidHeader {}
/// Missing cookie
#[derive(Debug)]
pub struct MissingCookie {
name: &'static str,
}
impl MissingCookie {
/// Retrieve the name of the cookie that was missing
pub fn name(&self) -> &str {
loop {}
}
@ -350,22 +350,22 @@ mod sealed {
loop {}
}
pub trait CombineRejection<E>: Send + Sized {
/// The type that should be returned when only 1 of the two
/// "rejections" occurs.
///
/// # For example:
///
/// `warp::any().and(warp::path("foo"))` has the following steps:
///
/// 1. Since this is `and`, only **one** of the rejections will occur,
/// and as soon as it does, it will be returned.
/// 2. `warp::any()` rejects with `Never`. So, it will never return `Never`.
/// 3. `warp::path()` rejects with `Rejection`. It may return `Rejection`.
///
/// Thus, if the above filter rejects, it will definitely be `Rejection`.
type One: IsReject + From<Self> + From<E> + Into<Rejection>;
/// The type that should be returned when both rejections occur,
/// and need to be combined.
type Combined: IsReject;
fn combine(self, other: E) -> Self::Combined;
}

View file

@ -45,59 +45,59 @@ pub(crate) use self::sealed::Reply_;
use self::sealed::BoxedReply;
#[doc(hidden)]
pub use crate::filters::reply as with;
/// Response type into which types implementing the `Reply` trait are convertable.
pub type Response = ::http::Response<Body>;
/// Returns an empty `Reply` with status code `200 OK`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // GET /just-ok returns an empty `200 OK`.
/// let route = warp::path("just-ok")
/// .map(|| {
/// println!("got a /just-ok request!");
/// warp::reply()
/// });
/// ```
#[inline]
pub fn reply() -> impl Reply {
StatusCode::OK
}
/// Convert the value into a `Reply` with the value encoded as JSON.
///
/// The passed value must implement [`Serialize`][ser]. Many
/// collections do, and custom domain types can have `Serialize` derived.
///
/// [ser]: https://serde.rs
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// // GET /ids returns a `200 OK` with a JSON array of ids:
/// // `[1, 3, 7, 13]`
/// let route = warp::path("ids")
/// .map(|| {
/// let our_ids = vec![1, 3, 7, 13];
/// warp::reply::json(&our_ids)
/// });
/// ```
///
/// # Note
///
/// If a type fails to be serialized into JSON, the error is logged at the
/// `error` level, and the returned `impl Reply` will be an empty
/// `500 Internal Server Error` response.
pub fn json<T>(val: &T) -> Json
where
T: Serialize,
{
loop {}
}
/// A JSON formatted reply.
#[allow(missing_debug_implementations)]
pub struct Json {
inner: Result<Vec<u8>, ()>,
@ -116,29 +116,29 @@ impl fmt::Display for ReplyJsonError {
}
}
impl StdError for ReplyJsonError {}
/// Reply with a body and `content-type` set to `text/html; charset=utf-8`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let body = r#"
/// <html>
/// <head>
/// <title>HTML with warp!</title>
/// </head>
/// <body>
/// <h1>warp + HTML = &hearts;</h1>
/// </body>
/// </html>
/// "#;
///
/// let route = warp::any()
/// .map(move || {
/// warp::reply::html(body)
/// });
/// ```
pub fn html<T>(body: T) -> Html<T>
where
Body: From<T>,
@ -146,7 +146,7 @@ where
{
loop {}
}
/// An HTML reply.
#[allow(missing_debug_implementations)]
pub struct Html<T> {
body: T,
@ -161,40 +161,40 @@ where
loop {}
}
}
/// Types that can be converted into a `Response`.
///
/// This trait is implemented for the following:
///
/// - `http::StatusCode`
/// - `http::Response<impl Into<hyper::Body>>`
/// - `String`
/// - `&'static str`
///
/// # Example
///
/// ```rust
/// use warp::{Filter, http::Response};
///
/// struct Message {
/// msg: String
/// }
///
/// impl warp::Reply for Message {
/// fn into_response(self) -> warp::reply::Response {
/// Response::new(format!("message: {}", self.msg).into())
/// }
/// }
///
/// fn handler() -> Message {
/// Message { msg: "Hello".to_string() }
/// }
///
/// let route = warp::any().map(handler);
/// ```
pub trait Reply: BoxedReply + Send {
/// Converts the given value into a [`Response`].
///
/// [`Response`]: type.Response.html
fn into_response(self) -> Response;
}
impl<T: Reply + ?Sized> Reply for Box<T> {
@ -205,25 +205,25 @@ impl<T: Reply + ?Sized> Reply for Box<T> {
fn _assert_object_safe() {
loop {}
}
/// Wrap an `impl Reply` to change its `StatusCode`.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(warp::reply)
/// .map(|reply| {
/// warp::reply::with_status(reply, warp::http::StatusCode::CREATED)
/// });
/// ```
pub fn with_status<T: Reply>(reply: T, status: StatusCode) -> WithStatus<T> {
loop {}
}
/// Wrap an `impl Reply` to change its `StatusCode`.
///
/// Returned by `warp::reply::with_status`.
#[derive(Debug)]
pub struct WithStatus<T> {
reply: T,
@ -234,19 +234,19 @@ impl<T: Reply> Reply for WithStatus<T> {
loop {}
}
}
/// Wrap an `impl Reply` to add a header when rendering.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let route = warp::any()
/// .map(warp::reply)
/// .map(|reply| {
/// warp::reply::with_header(reply, "server", "warp")
/// });
/// ```
pub fn with_header<T: Reply, K, V>(reply: T, name: K, value: V) -> WithHeader<T>
where
HeaderName: TryFrom<K>,
@ -256,9 +256,9 @@ where
{
loop {}
}
/// Wraps an `impl Reply` and adds a header when rendering.
///
/// Returned by `warp::reply::with_header`.
#[derive(Debug)]
pub struct WithHeader<T> {
header: Option<(HeaderName, HeaderValue)>,

View file

@ -16,7 +16,7 @@ use crate::filter::Filter;
use crate::reject::IsReject;
use crate::reply::Reply;
use crate::transport::Transport;
/// Create a `Server` with the provided `Filter`.
pub fn serve<F>(filter: F) -> Server<F>
where
F: Filter + Clone + Send + Sync + 'static,
@ -25,15 +25,15 @@ where
{
loop {}
}
/// A Warp Server ready to filter requests.
#[derive(Debug)]
pub struct Server<F> {
pipeline: bool,
filter: F,
}
/// A Warp Server ready to filter requests over TLS.
///
/// *This type requires the `"tls"` feature.*
#[cfg(feature = "tls")]
pub struct TlsServer<F> {
server: Server<F>,
@ -92,14 +92,14 @@ where
<F::Future as TryFuture>::Ok: Reply,
<F::Future as TryFuture>::Error: IsReject,
{
/// Run this `Server` forever on the current thread.
pub async fn run(self, addr: impl Into<SocketAddr>) {
loop {}
}
/// Run this `Server` forever on the current thread with a specific stream
/// of incoming connections.
///
/// This can be used for Unix Domain Sockets, or TLS, etc.
pub async fn run_incoming<I>(self, incoming: I)
where
I: TryStream + Send,
@ -108,12 +108,12 @@ where
{
loop {}
}
/// Bind to a socket address, returning a `Future` that can be
/// executed on the current runtime.
///
/// # Panics
///
/// Panics if we are unable to bind to the provided address.
pub fn bind(
self,
addr: impl Into<SocketAddr> + 'static,
@ -121,22 +121,22 @@ where
let (_, fut) = self.bind_ephemeral(addr);
fut
}
/// Bind to a socket address, returning a `Future` that can be
/// executed on any runtime.
///
/// In case we are unable to bind to the specified address, resolves to an
/// error and logs the reason.
pub async fn try_bind(self, addr: impl Into<SocketAddr>) {
loop {}
}
/// Bind to a possibly ephemeral socket address.
///
/// Returns the bound address and a `Future` that can be executed on
/// the current runtime.
///
/// # Panics
///
/// Panics if we are unable to bind to the provided address.
pub fn bind_ephemeral(
self,
addr: impl Into<SocketAddr>,
@ -150,13 +150,13 @@ where
});
(addr, srv)
}
/// Tried to bind a possibly ephemeral socket address.
///
/// Returns a `Result` which fails in case we are unable to bind with the
/// underlying error.
///
/// Returns the bound address and a `Future` that can be executed on
/// the current runtime.
pub fn try_bind_ephemeral(
self,
addr: impl Into<SocketAddr>,
@ -171,44 +171,44 @@ where
});
Ok((addr, srv))
}
/// Create a server with graceful shutdown signal.
///
/// When the signal completes, the server will start the graceful shutdown
/// process.
///
/// Returns the bound address and a `Future` that can be executed on
/// the current runtime.
///
/// # Example
///
/// ```no_run
/// use warp::Filter;
/// use futures_util::future::TryFutureExt;
/// use tokio::sync::oneshot;
///
/// # fn main() {
/// let routes = warp::any()
/// .map(|| "Hello, World!");
///
/// let (tx, rx) = oneshot::channel();
///
/// let (addr, server) = warp::serve(routes)
/// .bind_with_graceful_shutdown(([127, 0, 0, 1], 3030), async {
/// rx.await.ok();
/// });
///
/// // Spawn the server into a runtime
/// tokio::task::spawn(server);
///
/// Create a server with graceful shutdown signal.
///
/// When the signal completes, the server will start the graceful shutdown
/// Setup this `Server` with a specific stream of incoming connections.
///
/// This can be used for Unix Domain Sockets, or TLS, etc.
///
/// Returns a `Future` that can be executed on the current runtime.
pub fn serve_incoming<I>(self, incoming: I) -> impl Future<Output = ()>
where
I: TryStream + Send,
@ -219,15 +219,15 @@ where
self.serve_incoming2(incoming)
.instrument(tracing::info_span!("Server::serve_incoming"))
}
/// Setup this `Server` with a specific stream of incoming connections and a
/// signal to initiate graceful shutdown.
///
/// This can be used for Unix Domain Sockets, or TLS, etc.
///
/// When the signal completes, the server will start the graceful shutdown
/// process.
///
/// Returns a `Future` that can be executed on the current runtime.
pub fn serve_incoming_with_graceful_shutdown<I>(
self,
incoming: I,
@ -268,9 +268,9 @@ where
pub fn unstable_pipeline(mut self) -> Self {
loop {}
}
/// Configure a server to use TLS.
///
/// *This function requires the `"tls"` feature.*
#[cfg(feature = "tls")]
pub fn tls(self) -> TlsServer<F> {
loop {}
@ -283,69 +283,69 @@ where
<F::Future as TryFuture>::Ok: Reply,
<F::Future as TryFuture>::Error: IsReject,
{
/// Specify the file path to read the private key.
///
/// *This function requires the `"tls"` feature.*
pub fn key_path(self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Specify the file path to read the certificate.
///
/// *This function requires the `"tls"` feature.*
pub fn cert_path(self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Specify the file path to read the trust anchor for optional client authentication.
///
/// Anonymous and authenticated clients will be accepted. If no trust anchor is provided by any
/// of the `client_auth_` methods, then client authentication is disabled by default.
///
/// *This function requires the `"tls"` feature.*
pub fn client_auth_optional_path(self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Specify the file path to read the trust anchor for required client authentication.
///
/// Only authenticated clients will be accepted. If no trust anchor is provided by any of the
/// `client_auth_` methods, then client authentication is disabled by default.
///
/// *This function requires the `"tls"` feature.*
pub fn client_auth_required_path(self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Specify the in-memory contents of the private key.
///
/// *This function requires the `"tls"` feature.*
pub fn key(self, key: impl AsRef<[u8]>) -> Self {
loop {}
}
/// Specify the in-memory contents of the certificate.
///
/// *This function requires the `"tls"` feature.*
pub fn cert(self, cert: impl AsRef<[u8]>) -> Self {
loop {}
}
/// Specify the in-memory contents of the trust anchor for optional client authentication.
///
/// Anonymous and authenticated clients will be accepted. If no trust anchor is provided by any
/// of the `client_auth_` methods, then client authentication is disabled by default.
///
/// *This function requires the `"tls"` feature.*
pub fn client_auth_optional(self, trust_anchor: impl AsRef<[u8]>) -> Self {
loop {}
}
/// Specify the in-memory contents of the trust anchor for required client authentication.
///
/// Only authenticated clients will be accepted. If no trust anchor is provided by any of the
/// `client_auth_` methods, then client authentication is disabled by default.
///
/// *This function requires the `"tls"` feature.*
pub fn client_auth_required(self, trust_anchor: impl AsRef<[u8]>) -> Self {
loop {}
}
/// Specify the DER-encoded OCSP response.
///
/// *This function requires the `"tls"` feature.*
pub fn ocsp_resp(self, resp: impl AsRef<[u8]>) -> Self {
loop {}
}
@ -355,37 +355,37 @@ where
{
loop {}
}
/// Run this `TlsServer` forever on the current thread.
///
/// *This function requires the `"tls"` feature.*
pub async fn run(self, addr: impl Into<SocketAddr>) {
loop {}
}
/// Bind to a socket address, returning a `Future` that can be
/// executed on a runtime.
///
/// *This function requires the `"tls"` feature.*
pub async fn bind(self, addr: impl Into<SocketAddr>) {
loop {}
}
/// Bind to a possibly ephemeral socket address.
///
/// Returns the bound address and a `Future` that can be executed on
/// the current runtime.
///
/// *This function requires the `"tls"` feature.*
pub fn bind_ephemeral(
self,
addr: impl Into<SocketAddr>,
) -> (SocketAddr, impl Future<Output = ()> + 'static) {
loop {}
}
/// Create a server with graceful shutdown signal.
///
/// When the signal completes, the server will start the graceful shutdown
/// process.
///
/// *This function requires the `"tls"` feature.*
pub fn bind_with_graceful_shutdown(
self,
addr: impl Into<SocketAddr> + 'static,

View file

@ -115,94 +115,94 @@ use crate::Request;
#[cfg(feature = "websocket")]
use crate::{Sink, Stream};
use self::inner::OneOrTuple;
/// Starts a new test `RequestBuilder`.
pub fn request() -> RequestBuilder {
loop {}
}
/// Starts a new test `WsBuilder`.
#[cfg(feature = "websocket")]
pub fn ws() -> WsBuilder {
loop {}
}
/// A request builder for testing filters.
///
/// See [module documentation](crate::test) for an overview.
#[must_use = "RequestBuilder does nothing on its own"]
#[derive(Debug)]
pub struct RequestBuilder {
remote_addr: Option<SocketAddr>,
req: Request,
}
/// A Websocket builder for testing filters.
///
/// See [module documentation](crate::test) for an overview.
#[cfg(feature = "websocket")]
#[must_use = "WsBuilder does nothing on its own"]
#[derive(Debug)]
pub struct WsBuilder {
req: RequestBuilder,
}
/// A test client for Websocket filters.
#[cfg(feature = "websocket")]
pub struct WsClient {
tx: mpsc::UnboundedSender<crate::ws::Message>,
rx: mpsc::UnboundedReceiver<Result<crate::ws::Message, crate::error::Error>>,
}
/// An error from Websocket filter tests.
#[derive(Debug)]
pub struct WsError {
cause: Box<dyn StdError + Send + Sync>,
}
impl RequestBuilder {
/// Sets the method of this builder.
///
/// The default if not set is `GET`.
///
/// # Example
///
/// ```
/// let req = warp::test::request()
/// .method("POST");
/// ```
///
/// # Panic
///
/// This panics if the passed string is not able to be parsed as a valid
/// `Method`.
pub fn method(mut self, method: &str) -> Self {
loop {}
}
/// Sets the request path of this builder.
///
/// The default is not set is `/`.
///
/// # Example
///
/// ```
/// let req = warp::test::request()
/// .path("/todos/33");
/// ```
///
/// # Panic
///
/// This panics if the passed string is not able to be parsed as a valid
/// `Uri`.
pub fn path(mut self, p: &str) -> Self {
loop {}
}
/// Set a header for this request.
///
/// # Example
///
/// ```
/// let req = warp::test::request()
/// .header("accept", "application/json");
/// ```
///
/// # Panic
///
/// This panics if the passed strings are not able to be parsed as a valid
/// `HeaderName` and `HeaderValue`.
pub fn header<K, V>(mut self, key: K, value: V) -> Self
where
HeaderName: TryFrom<K>,
@ -210,76 +210,76 @@ impl RequestBuilder {
{
loop {}
}
/// Set the remote address of this request
///
/// Default is no remote address.
///
/// # Example
/// ```
/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
///
/// let req = warp::test::request()
/// .remote_addr(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080));
/// ```
pub fn remote_addr(mut self, addr: SocketAddr) -> Self {
loop {}
}
/// Add a type to the request's `http::Extensions`.
pub fn extension<T>(mut self, ext: T) -> Self
where
T: Send + Sync + 'static,
{
loop {}
}
/// Set the bytes of this request body.
///
/// Default is an empty body.
///
/// # Example
///
/// ```
/// let req = warp::test::request()
/// .body("foo=bar&baz=quux");
/// ```
pub fn body(mut self, body: impl AsRef<[u8]>) -> Self {
loop {}
}
/// Set the bytes of this request body by serializing a value into JSON.
///
/// # Example
///
/// ```
/// let req = warp::test::request()
/// .json(&true);
/// ```
pub fn json(mut self, val: &impl Serialize) -> Self {
loop {}
}
/// Tries to apply the `Filter` on this request.
///
/// # Example
///
/// ```no_run
/// async {
/// let param = warp::path::param::<u32>();
///
/// let ex = warp::test::request()
/// .path("/41")
/// .filter(&param)
/// .await
/// .unwrap();
///
/// assert_eq!(ex, 41);
///
/// assert!(
/// warp::test::request()
/// .path("/foo")
/// .filter(&param)
/// .await
/// .is_err()
/// );
///};
/// ```
pub async fn filter<F>(
self,
f: &F,
@ -292,30 +292,30 @@ impl RequestBuilder {
{
loop {}
}
/// Returns whether the `Filter` matches this request, or rejects it.
///
/// # Example
///
/// ```no_run
/// async {
/// let get = warp::get();
/// let post = warp::post();
///
/// assert!(
/// warp::test::request()
/// .method("GET")
/// .matches(&get)
/// .await
/// );
///
/// assert!(
/// !warp::test::request()
/// .method("GET")
/// .matches(&post)
/// .await
/// );
///};
/// ```
pub async fn matches<F>(self, f: &F) -> bool
where
F: Filter,
@ -325,9 +325,9 @@ impl RequestBuilder {
{
loop {}
}
/// Returns `Response` provided by applying the `Filter`.
///
/// This requires that the supplied `Filter` return a [`Reply`](Reply).
pub async fn reply<F>(self, f: &F) -> Response<Bytes>
where
F: Filter + 'static,
@ -339,37 +339,37 @@ impl RequestBuilder {
}
#[cfg(feature = "websocket")]
impl WsBuilder {
/// Sets the request path of this builder.
///
/// The default is not set is `/`.
///
/// # Example
///
/// ```
/// let req = warp::test::ws()
/// .path("/chat");
/// ```
///
/// # Panic
///
/// This panics if the passed string is not able to be parsed as a valid
/// `Uri`.
pub fn path(self, p: &str) -> Self {
loop {}
}
/// Set a header for this request.
///
/// # Example
///
/// ```
/// let req = warp::test::ws()
/// .header("foo", "bar");
/// ```
///
/// # Panic
///
/// This panics if the passed strings are not able to be parsed as a valid
/// `HeaderName` and `HeaderValue`.
pub fn header<K, V>(self, key: K, value: V) -> Self
where
HeaderName: TryFrom<K>,
@ -377,30 +377,30 @@ impl WsBuilder {
{
loop {}
}
/// Execute this Websocket request against the provided filter.
///
/// If the handshake succeeds, returns a `WsClient`.
///
/// # Example
///
/// ```no_run
/// use futures_util::future;
/// use warp::Filter;
/// #[tokio::main]
/// # async fn main() {
///
/// // Some route that accepts websockets (but drops them immediately).
/// let route = warp::ws()
/// .map(|ws: warp::ws::Ws| {
/// ws.on_upgrade(|_| future::ready(()))
/// });
///
/// let client = warp::test::ws()
/// .handshake(route)
/// .await
/// .expect("handshake");
/// # }
/// ```
pub async fn handshake<F>(self, f: F) -> Result<WsClient, WsError>
where
F: Filter + Clone + Send + Sync + 'static,
@ -412,19 +412,19 @@ impl WsBuilder {
}
#[cfg(feature = "websocket")]
impl WsClient {
/// Send a "text" websocket message to the server.
pub async fn send_text(&mut self, text: impl Into<String>) {
loop {}
}
/// Send a websocket message to the server.
pub async fn send(&mut self, msg: crate::ws::Message) {
loop {}
}
/// Receive a websocket message from the server.
pub async fn recv(&mut self) -> Result<crate::filters::ws::Message, WsError> {
loop {}
}
/// Assert the server has closed the connection.
pub async fn recv_closed(&mut self) -> Result<(), WsError> {
loop {}
}

View file

@ -18,19 +18,19 @@ use tokio_rustls::rustls::{
},
Certificate, Error as TlsError, PrivateKey, RootCertStore, ServerConfig,
};
/// Represents errors that can occur building the TlsConfig
#[derive(Debug)]
pub(crate) enum TlsConfigError {
Io(io::Error),
/// An Error parsing the Certificate
CertParseError,
/// An Error parsing a Pkcs8 key
Pkcs8ParseError,
/// An Error parsing a Rsa key
RsaParseError,
/// An error from an empty key
EmptyKey,
/// An error from an invalid key
InvalidKey(TlsError),
}
impl fmt::Display for TlsConfigError {
@ -39,16 +39,16 @@ impl fmt::Display for TlsConfigError {
}
}
impl std::error::Error for TlsConfigError {}
/// Tls client authentication configuration.
pub(crate) enum TlsClientAuth {
/// No client auth.
Off,
/// Allow any anonymous or authenticated client.
Optional(Box<dyn Read + Send + Sync>),
/// Allow any authenticated client.
Required(Box<dyn Read + Send + Sync>),
}
/// Builder to set the configuration for the Tls server.
pub(crate) struct TlsConfigBuilder {
cert: Box<dyn Read + Send + Sync>,
key: Box<dyn Read + Send + Sync>,
@ -61,55 +61,55 @@ impl fmt::Debug for TlsConfigBuilder {
}
}
impl TlsConfigBuilder {
/// Create a new TlsConfigBuilder
pub(crate) fn new() -> TlsConfigBuilder {
loop {}
}
/// sets the Tls key via File Path, returns `TlsConfigError::IoError` if the file cannot be open
pub(crate) fn key_path(mut self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// sets the Tls key via bytes slice
pub(crate) fn key(mut self, key: &[u8]) -> Self {
loop {}
}
/// Specify the file path for the TLS certificate to use.
pub(crate) fn cert_path(mut self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// sets the Tls certificate via bytes slice
pub(crate) fn cert(mut self, cert: &[u8]) -> Self {
loop {}
}
/// Sets the trust anchor for optional Tls client authentication via file path.
///
/// Anonymous and authenticated clients will be accepted. If no trust anchor is provided by any
/// of the `client_auth_` methods, then client authentication is disabled by default.
pub(crate) fn client_auth_optional_path(mut self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Sets the trust anchor for optional Tls client authentication via bytes slice.
///
/// Anonymous and authenticated clients will be accepted. If no trust anchor is provided by any
/// of the `client_auth_` methods, then client authentication is disabled by default.
pub(crate) fn client_auth_optional(mut self, trust_anchor: &[u8]) -> Self {
loop {}
}
/// Sets the trust anchor for required Tls client authentication via file path.
///
/// Only authenticated clients will be accepted. If no trust anchor is provided by any of the
/// `client_auth_` methods, then client authentication is disabled by default.
pub(crate) fn client_auth_required_path(mut self, path: impl AsRef<Path>) -> Self {
loop {}
}
/// Sets the trust anchor for required Tls client authentication via bytes slice.
///
/// Only authenticated clients will be accepted. If no trust anchor is provided by any of the
/// `client_auth_` methods, then client authentication is disabled by default.
pub(crate) fn client_auth_required(mut self, trust_anchor: &[u8]) -> Self {
loop {}
}
/// sets the DER-encoded OCSP response
pub(crate) fn ocsp_resp(mut self, ocsp_resp: &[u8]) -> Self {
loop {}
}