diff options
Diffstat (limited to 'vendor/hyper/src/service')
| -rw-r--r-- | vendor/hyper/src/service/http.rs | 52 | ||||
| -rw-r--r-- | vendor/hyper/src/service/mod.rs | 30 | ||||
| -rw-r--r-- | vendor/hyper/src/service/service.rs | 100 | ||||
| -rw-r--r-- | vendor/hyper/src/service/util.rs | 82 |
4 files changed, 264 insertions, 0 deletions
diff --git a/vendor/hyper/src/service/http.rs b/vendor/hyper/src/service/http.rs new file mode 100644 index 00000000..dd174316 --- /dev/null +++ b/vendor/hyper/src/service/http.rs @@ -0,0 +1,52 @@ +use std::error::Error as StdError; +use std::future::Future; + +use crate::body::Body; +use crate::service::service::Service; +use crate::{Request, Response}; + +/// An asynchronous function from `Request` to `Response`. +pub trait HttpService<ReqBody>: sealed::Sealed<ReqBody> { + /// The `Body` body of the `http::Response`. + type ResBody: Body; + + /// The error type that can occur within this `Service`. + /// + /// Note: Returning an `Error` to a hyper server will cause the connection + /// to be abruptly aborted. In most cases, it is better to return a `Response` + /// with a 4xx or 5xx status code. + type Error: Into<Box<dyn StdError + Send + Sync>>; + + /// The `Future` returned by this `Service`. + type Future: Future<Output = Result<Response<Self::ResBody>, Self::Error>>; + + #[doc(hidden)] + fn call(&mut self, req: Request<ReqBody>) -> Self::Future; +} + +impl<T, B1, B2> HttpService<B1> for T +where + T: Service<Request<B1>, Response = Response<B2>>, + B2: Body, + T::Error: Into<Box<dyn StdError + Send + Sync>>, +{ + type ResBody = B2; + + type Error = T::Error; + type Future = T::Future; + + fn call(&mut self, req: Request<B1>) -> Self::Future { + Service::call(self, req) + } +} + +impl<T, B1, B2> sealed::Sealed<B1> for T +where + T: Service<Request<B1>, Response = Response<B2>>, + B2: Body, +{ +} + +mod sealed { + pub trait Sealed<T> {} +} diff --git a/vendor/hyper/src/service/mod.rs b/vendor/hyper/src/service/mod.rs new file mode 100644 index 00000000..28ffaddb --- /dev/null +++ b/vendor/hyper/src/service/mod.rs @@ -0,0 +1,30 @@ +//! Asynchronous Services +//! +//! A [`Service`] is a trait representing an asynchronous +//! function of a request to a response. It's similar to +//! `async fn(Request) -> Result<Response, Error>`. +//! +//! The argument and return value isn't strictly required to be for HTTP. +//! Therefore, hyper uses several "trait aliases" to reduce clutter around +//! bounds. These are: +//! +//! - `HttpService`: This is blanketly implemented for all types that +//! implement `Service<http::Request<B1>, Response = http::Response<B2>>`. +//! +//! # HttpService +//! +//! In hyper, especially in the server setting, a `Service` is usually bound +//! to a single connection. It defines how to respond to **all** requests that +//! connection will receive. +//! +//! The helper [`service_fn`] should be sufficient for most cases, but +//! if you need to implement `Service` for a type manually, you can follow the example +//! in `service_struct_impl.rs`. + +mod http; +mod service; +mod util; + +pub use self::http::HttpService; +pub use self::service::Service; +pub use self::util::service_fn; diff --git a/vendor/hyper/src/service/service.rs b/vendor/hyper/src/service/service.rs new file mode 100644 index 00000000..42c18e72 --- /dev/null +++ b/vendor/hyper/src/service/service.rs @@ -0,0 +1,100 @@ +use std::future::Future; + +/// An asynchronous function from a `Request` to a `Response`. +/// +/// The `Service` trait is a simplified interface making it easy to write +/// network applications in a modular and reusable way, decoupled from the +/// underlying protocol. +/// +/// # Functional +/// +/// A `Service` is a function of a `Request`. It immediately returns a +/// `Future` representing the eventual completion of processing the +/// request. The actual request processing may happen at any time in the +/// future, on any thread or executor. The processing may depend on calling +/// other services. At some point in the future, the processing will complete, +/// and the `Future` will resolve to a response or error. +/// +/// At a high level, the `Service::call` function represents an RPC request. The +/// `Service` value can be a server or a client. +pub trait Service<Request> { + /// Responses given by the service. + type Response; + + /// Errors produced by the service. + /// + /// Note: Returning an `Error` to a hyper server, the behavior depends on the + /// protocol. In most cases, hyper will cause the connection to be abruptly aborted. + /// It will abort the request however the protocol allows, either with some sort of RST_STREAM, + /// or killing the connection if that doesn't exist. + type Error; + + /// The future response value. + type Future: Future<Output = Result<Self::Response, Self::Error>>; + + /// Process the request and return the response asynchronously. + /// `call` takes `&self` instead of `mut &self` because: + /// - It prepares the way for async fn, + /// since then the future only borrows `&self`, and thus a Service can concurrently handle + /// multiple outstanding requests at once. + /// - It's clearer that Services can likely be cloned + /// - To share state across clones, you generally need `Arc<Mutex<_>>` + /// That means you're not really using the `&mut self` and could do with a `&self`. + /// The discussion on this is here: <https://github.com/hyperium/hyper/issues/3040> + fn call(&self, req: Request) -> Self::Future; +} + +impl<Request, S: Service<Request> + ?Sized> Service<Request> for &'_ S { + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn call(&self, req: Request) -> Self::Future { + (**self).call(req) + } +} + +impl<Request, S: Service<Request> + ?Sized> Service<Request> for &'_ mut S { + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn call(&self, req: Request) -> Self::Future { + (**self).call(req) + } +} + +impl<Request, S: Service<Request> + ?Sized> Service<Request> for Box<S> { + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn call(&self, req: Request) -> Self::Future { + (**self).call(req) + } +} + +impl<Request, S: Service<Request> + ?Sized> Service<Request> for std::rc::Rc<S> { + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn call(&self, req: Request) -> Self::Future { + (**self).call(req) + } +} + +impl<Request, S: Service<Request> + ?Sized> Service<Request> for std::sync::Arc<S> { + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + #[inline] + fn call(&self, req: Request) -> Self::Future { + (**self).call(req) + } +} diff --git a/vendor/hyper/src/service/util.rs b/vendor/hyper/src/service/util.rs new file mode 100644 index 00000000..3e017a78 --- /dev/null +++ b/vendor/hyper/src/service/util.rs @@ -0,0 +1,82 @@ +use std::error::Error as StdError; +use std::fmt; +use std::future::Future; +use std::marker::PhantomData; + +use crate::body::Body; +use crate::service::service::Service; +use crate::{Request, Response}; + +/// Create a `Service` from a function. +/// +/// # Example +/// +/// ``` +/// use bytes::Bytes; +/// use hyper::{body, Request, Response, Version}; +/// use http_body_util::Full; +/// use hyper::service::service_fn; +/// +/// let service = service_fn(|req: Request<body::Incoming>| async move { +/// if req.version() == Version::HTTP_11 { +/// Ok(Response::new(Full::<Bytes>::from("Hello World"))) +/// } else { +/// // Note: it's usually better to return a Response +/// // with an appropriate StatusCode instead of an Err. +/// Err("not HTTP/1.1, abort connection") +/// } +/// }); +/// ``` +pub fn service_fn<F, R, S>(f: F) -> ServiceFn<F, R> +where + F: Fn(Request<R>) -> S, + S: Future, +{ + ServiceFn { + f, + _req: PhantomData, + } +} + +/// Service returned by [`service_fn`] +pub struct ServiceFn<F, R> { + f: F, + _req: PhantomData<fn(R)>, +} + +impl<F, ReqBody, Ret, ResBody, E> Service<Request<ReqBody>> for ServiceFn<F, ReqBody> +where + F: Fn(Request<ReqBody>) -> Ret, + ReqBody: Body, + Ret: Future<Output = Result<Response<ResBody>, E>>, + E: Into<Box<dyn StdError + Send + Sync>>, + ResBody: Body, +{ + type Response = crate::Response<ResBody>; + type Error = E; + type Future = Ret; + + fn call(&self, req: Request<ReqBody>) -> Self::Future { + (self.f)(req) + } +} + +impl<F, R> fmt::Debug for ServiceFn<F, R> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("impl Service").finish() + } +} + +impl<F, R> Clone for ServiceFn<F, R> +where + F: Clone, +{ + fn clone(&self) -> Self { + ServiceFn { + f: self.f.clone(), + _req: PhantomData, + } + } +} + +impl<F, R> Copy for ServiceFn<F, R> where F: Copy {} |
