1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! Types and traits giving an interface between low-level http server implementations //! and services that use them. The interface is based on the `std::futures` API. //! //! ## Example //! ```rust,no_run //! use futures::{ //! future::{self, BoxFuture, FutureExt}, //! }; //! use http_service::{HttpService, Response}; //! use std::net::{IpAddr, Ipv4Addr, SocketAddr}; //! //! struct Server { //! message: Vec<u8>, //! } //! //! impl Server { //! fn create(message: Vec<u8>) -> Server { //! Server { //! message, //! } //! } //! //! pub fn run(s: Server) { //! let a = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); //! http_service_hyper::run(s, a); //! } //! } //! //! impl HttpService for Server { //! type Connection = (); //! type ConnectionFuture = future::Ready<Result<(), std::io::Error>>; //! type ResponseFuture = BoxFuture<'static, Result<http_service::Response, std::io::Error>>; //! //! fn connect(&self) -> Self::ConnectionFuture { //! future::ok(()) //! } //! //! fn respond(&self, _conn: &mut (), _req: http_service::Request) -> Self::ResponseFuture { //! let message = self.message.clone(); //! async move { Ok(Response::new(http_service::Body::from(message))) }.boxed() //! } //! } //! //! fn main() { //! let s = Server::create(String::from("Hello, World").into_bytes()); //! Server::run(s); //! } //! ``` #![forbid(future_incompatible, rust_2018_idioms)] #![deny(missing_debug_implementations, nonstandard_style)] #![warn(missing_docs, missing_doc_code_examples)] #![cfg_attr(any(feature = "nightly", test), feature(external_doc))] #![cfg_attr(feature = "nightly", doc(include = "../README.md"))] #![cfg_attr(test, deny(warnings))] use bytes::Bytes; use futures::{ future, prelude::*, stream::{self, BoxStream}, task::{Context, Poll}, }; use std::fmt; use std::pin::Pin; #[cfg(test)] #[doc(include = "../README.md")] const _README: () = (); /// The raw body of an http request or response. /// /// A body is a stream of `Bytes` values, which are shared handles to byte buffers. /// Both `Body` and `Bytes` values can be easily created from standard owned byte buffer types /// like `Vec<u8>` or `String`, using the `From` trait. pub struct Body { stream: BoxStream<'static, Result<Bytes, std::io::Error>>, } impl Body { /// Create an empty body. pub fn empty() -> Self { Body::from_stream(stream::empty()) } /// Create a body from a stream of `Bytes` pub fn from_stream<S>(s: S) -> Self where S: Stream<Item = Result<Bytes, std::io::Error>> + Send + 'static, { Self { stream: s.boxed() } } /// Reads the stream into a new `Vec`. #[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/4037 pub async fn into_vec(mut self) -> std::io::Result<Vec<u8>> { let mut bytes = Vec::new(); while let Some(chunk) = self.next().await { bytes.extend(chunk?); } Ok(bytes) } } impl<T: Into<Bytes> + Send> From<T> for Body { fn from(x: T) -> Self { Self::from_stream(stream::once(future::ok(x.into()))) } } impl Unpin for Body {} impl Stream for Body { type Item = Result<Bytes, std::io::Error>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { self.stream.poll_next_unpin(cx) } } impl fmt::Debug for Body { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Body").finish() } } /// An HTTP request with a streaming body. pub type Request = http::Request<Body>; /// An HTTP response with a streaming body. pub type Response = http::Response<Body>; /// An async HTTP service /// /// An instance represents a service as a whole. The associated `Conn` type /// represents a particular connection, and may carry connection-specific state. pub trait HttpService: Send + Sync + 'static { /// An individual connection. /// /// This associated type is used to establish and hold any per-connection state /// needed by the service. type Connection: Send + 'static; /// A future for setting up an individual connection. /// /// This method is called each time the server receives a new connection request, /// but before actually exchanging any data with the client. /// /// Returning an error will result in the server immediately dropping /// the connection. type ConnectionFuture: Send + 'static + TryFuture<Ok = Self::Connection>; /// Initiate a new connection. /// /// This method is given access to the global service (`&self`), which may provide /// handles to connection pools, thread pools, or other global data. fn connect(&self) -> Self::ConnectionFuture; /// The async computation for producing the response. /// /// Returning an error will result in the server immediately dropping /// the connection. It is usually preferable to instead return an HTTP response /// with an error status code. type ResponseFuture: Send + 'static + TryFuture<Ok = Response>; /// Begin handling a single request. /// /// The handler is given shared access to the service itself, and mutable access /// to the state for the connection where the request is taking place. fn respond(&self, conn: &mut Self::Connection, req: Request) -> Self::ResponseFuture; } impl<F, R> HttpService for F where F: Send + Sync + 'static + Fn(Request) -> R, R: Send + 'static + TryFuture<Ok = Response>, R::Error: Send, { type Connection = (); type ConnectionFuture = future::Ready<Result<(), R::Error>>; fn connect(&self) -> Self::ConnectionFuture { future::ok(()) } type ResponseFuture = R; fn respond(&self, _: &mut (), req: Request) -> Self::ResponseFuture { (self)(req) } }