diff --git a/hyper/src/body/aggregate.rs b/hyper/src/body/aggregate.rs index 9966241..2599b12 100644 --- a/hyper/src/body/aggregate.rs +++ b/hyper/src/body/aggregate.rs @@ -3,16 +3,16 @@ use bytes::Buf; use super::HttpBody; use crate::common::buf::BufList; -/// Aggregate the data buffers from a body asynchronously. -/// -/// The returned `impl Buf` groups the `Buf`s from the `HttpBody` without -/// copying them. This is ideal if you don't require a contiguous buffer. -/// -/// # Note -/// -/// Care needs to be taken if the remote is untrusted. The function doesn't implement any length -/// checks and an malicious peer might make it consume arbitrary amounts of memory. Checking the -/// `Content-Length` is a possibility, but it is not strictly mandated to be present. + + + + + + + + + + pub async fn aggregate(body: T) -> Result where T: HttpBody, diff --git a/hyper/src/body/body.rs b/hyper/src/body/body.rs index 7e212d9..268e20d 100644 --- a/hyper/src/body/body.rs +++ b/hyper/src/body/body.rs @@ -18,18 +18,18 @@ use crate::common::{task, watch, Pin, Poll}; use crate::proto::h2::ping; type BodySender = mpsc::Sender>; type TrailersSender = oneshot::Sender; -/// A stream of `Bytes`, used when receiving bodies. -/// -/// A good default [`HttpBody`](crate::body::HttpBody) to use in many -/// applications. -/// -/// Note: To read the full body, use [`body::to_bytes`](crate::body::to_bytes) -/// or [`body::aggregate`](crate::body::aggregate). + + + + + + + #[must_use = "streams do nothing unless polled"] pub struct Body { kind: Kind, - /// Keep the extra bits in an `Option>`, so that - /// Body stays small in the common case (no extras needed). + + extra: Option>, } enum Kind { @@ -58,43 +58,43 @@ enum Kind { ), } struct Extra { - /// Allow the client to pass a future to delay the `Body` from returning - /// EOF. This allows the `Client` to try to put the idle connection - /// back into the pool before the body is "finished". - /// - /// The reason for this is so that creating a new request after finishing - /// streaming the body of a response could sometimes result in creating - /// a brand new connection, since the pool didn't know about the idle - /// connection yet. + + + + + + + + delayed_eof: Option, } #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))] type DelayEofUntil = oneshot::Receiver; enum DelayEof { - /// Initial state, stream hasn't seen EOF yet. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "client")] NotEof(DelayEofUntil), - /// Transitions to this state once we've seen `poll` try to - /// return EOF (`None`). This future is then polled, and - /// when it completes, the Body finally returns EOF (`None`). + + + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "client")] Eof(DelayEofUntil), } -/// A sender half created through [`Body::channel()`]. -/// -/// Useful when wanting to stream chunks from another thread. -/// -/// ## Body Closing -/// -/// Note that the request body will always be closed normally when the sender is dropped (meaning -/// that the empty terminating chunk will be sent to the remote). If you desire to close the -/// connection with an incomplete response (e.g. in the case of an error during asynchronous -/// processing), call the [`Sender::abort()`] method to abort the body in an abnormal fashion. -/// -/// [`Body::channel()`]: struct.Body.html#method.channel -/// [`Sender::abort()`]: struct.Sender.html#method.abort + + + + + + + + + + + + + #[must_use = "Sender does nothing unless sent on"] pub struct Sender { want_rx: watch::Receiver, @@ -102,41 +102,41 @@ pub struct Sender { trailers_tx: Option, } impl Body { - /// Create an empty `Body` stream. - /// - /// # Example - /// - /// ``` - /// use hyper::{Body, Request}; - /// - /// // create a `GET /` request - /// let get = Request::new(Body::empty()); - /// ``` + + + + + + + + + + #[inline] pub fn empty() -> Body { loop {} } - /// Wrap a futures `Stream` in a box inside `Body`. - /// - /// # Example - /// - /// ``` - /// # use hyper::Body; - /// let chunks: Vec> = vec![ - /// Ok("hello"), - /// Ok(" "), - /// Ok("world"), - /// ]; - /// - /// let stream = futures_util::stream::iter(chunks); - /// - /// let body = Body::wrap_stream(stream); - /// ``` - /// - /// # Optional - /// - /// This function requires enabling the `stream` feature in your - /// `Cargo.toml`. + + + + + + + + + + + + + + + + + + + + + #[cfg(feature = "stream")] #[cfg_attr(docsrs, doc(cfg(feature = "stream")))] pub fn wrap_stream(stream: S) -> Body @@ -153,7 +153,7 @@ impl Body { } } impl Default for Body { - /// Returns `Body::empty()`. + #[inline] fn default() -> Body { loop {} @@ -188,10 +188,10 @@ impl fmt::Debug for Body { loop {} } } -/// # Optional -/// -/// This function requires enabling the `stream` feature in your -/// `Cargo.toml`. + + + + #[cfg(feature = "stream")] impl Stream for Body { type Item = crate::Result; @@ -202,10 +202,10 @@ impl Stream for Body { loop {} } } -/// # Optional -/// -/// This function requires enabling the `stream` feature in your -/// `Cargo.toml`. + + + + #[cfg(feature = "stream")] impl From>> + Send>> for Body { diff --git a/hyper/src/body/length.rs b/hyper/src/body/length.rs index edce3cc..d1c7ee5 100644 --- a/hyper/src/body/length.rs +++ b/hyper/src/body/length.rs @@ -15,20 +15,20 @@ impl DecodedLength { pub(crate) fn new(len: u64) -> Self { loop {} } - /// Takes the length as a content-length without other checks. - /// - /// Should only be called if previously confirmed this isn't - /// CLOSE_DELIMITED or CHUNKED. + + + + #[inline] #[cfg(feature = "http1")] pub(crate) fn danger_len(self) -> u64 { loop {} } - /// Converts to an Option representing a Known or Unknown length. + pub(crate) fn into_opt(self) -> Option { loop {} } - /// Checks the `u64` is within the maximum allowed for content-length. + #[cfg(any(feature = "http1", feature = "http2"))] pub(crate) fn checked_new(len: u64) -> Result { loop {} @@ -36,11 +36,11 @@ impl DecodedLength { pub(crate) fn sub_if(&mut self, amt: u64) { loop {} } - /// Returns whether this represents an exact length. - /// - /// This includes 0, which of course is an exact known length. - /// - /// It would return false if "chunked" or otherwise size-unknown. + + + + + #[cfg(feature = "http2")] pub(crate) fn is_exact(&self) -> bool { loop {} diff --git a/hyper/src/body/to_bytes.rs b/hyper/src/body/to_bytes.rs index 8a90fa3..1f17541 100644 --- a/hyper/src/body/to_bytes.rs +++ b/hyper/src/body/to_bytes.rs @@ -1,47 +1,47 @@ use bytes::{Bytes}; use super::HttpBody; -/// Concatenate the buffers from a body into a single `Bytes` asynchronously. -/// -/// This may require copying the data into a single buffer. If you don't need -/// a contiguous buffer, prefer the [`aggregate`](crate::body::aggregate()) -/// function. -/// -/// # Note -/// -/// Care needs to be taken if the remote is untrusted. The function doesn't implement any length -/// checks and an malicious peer might make it consume arbitrary amounts of memory. Checking the -/// `Content-Length` is a possibility, but it is not strictly mandated to be present. -/// -/// # Example -/// -/// ``` -/// # #[cfg(all(feature = "client", feature = "tcp", any(feature = "http1", feature = "http2")))] -/// # async fn doc() -> hyper::Result<()> { -/// use hyper::{body::HttpBody}; -/// -/// # let request = hyper::Request::builder() -/// # .method(hyper::Method::POST) -/// # .uri("http://httpbin.org/post") -/// # .header("content-type", "application/json") -/// # .body(hyper::Body::from(r#"{"library":"hyper"}"#)).unwrap(); -/// # let client = hyper::Client::new(); -/// let response = client.request(request).await?; -/// -/// const MAX_ALLOWED_RESPONSE_SIZE: u64 = 1024; -/// -/// let response_content_length = match response.body().size_hint().upper() { -/// Some(v) => v, -/// None => MAX_ALLOWED_RESPONSE_SIZE + 1 // Just to protect ourselves from a malicious response -/// }; -/// -/// if response_content_length < MAX_ALLOWED_RESPONSE_SIZE { -/// let body_bytes = hyper::body::to_bytes(response.into_body()).await?; -/// println!("body: {:?}", body_bytes); -/// } -/// -/// # Ok(()) -/// # } -/// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub async fn to_bytes(body: T) -> Result where T: HttpBody, diff --git a/hyper/src/client/client.rs b/hyper/src/client/client.rs index 39de2a6..77df110 100644 --- a/hyper/src/client/client.rs +++ b/hyper/src/client/client.rs @@ -21,10 +21,10 @@ use crate::common::{ Lazy, Pin, Poll, }; use crate::rt::Executor; -/// A Client to make outgoing HTTP requests. -/// -/// `Client` is cheap to clone and cloning is the recommended way to share a `Client`. The -/// underlying connection pool will be reused. + + + + #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Client { config: Config, @@ -38,9 +38,9 @@ struct Config { set_host: bool, ver: Ver, } -/// A `Future` that will resolve to an HTTP Response. -/// -/// This is returned by `Client::request` (and `Client::get`). + + + #[must_use = "futures do nothing unless polled"] pub struct ResponseFuture { inner: SyncWrapper< @@ -49,13 +49,13 @@ pub struct ResponseFuture { } #[cfg(feature = "tcp")] impl Client { - /// Create a new Client with the default [config](Builder). - /// - /// # Note - /// - /// The default connector does **not** handle TLS. Speaking to `https` - /// destinations will require [configuring a connector that implements - /// TLS](https://hyper.rs/guides/client/configuration). + + + + + + + #[cfg_attr(docsrs, doc(cfg(feature = "tcp")))] #[inline] pub(crate) fn new() -> Client { @@ -69,25 +69,25 @@ impl Default for Client { } } impl Client<(), Body> { - /// Create a builder to configure a new `Client`. - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "runtime")] - /// # fn run () { - /// use std::time::Duration; - /// use hyper::Client; - /// - /// let client = Client::builder() - /// .pool_idle_timeout(Duration::from_secs(30)) - /// .http2_only(true) - /// .build_http(); - /// # let infer: Client<_, hyper::Body> = client; - /// # drop(infer); - /// # } - /// # fn main() {} - /// ``` + + + + + + + + + + + + + + + + + + + #[inline] pub(crate) fn builder() -> Builder { loop {} @@ -100,54 +100,54 @@ where B::Data: Send, B::Error: Into>, { - /// Send a `GET` request to the supplied `Uri`. - /// - /// # Note - /// - /// This requires that the `HttpBody` type have a `Default` implementation. - /// It *should* return an "empty" version of itself, such that - /// `HttpBody::is_end_stream` is `true`. - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "runtime")] - /// # fn run () { - /// use hyper::{Client, Uri}; - /// - /// let client = Client::new(); - /// - /// let future = client.get(Uri::from_static("http://httpbin.org/ip")); - /// # } - /// # fn main() {} - /// ``` + + + + + + + + + + + + + + + + + + + + + pub(crate) fn get(&self, uri: Uri) -> ResponseFuture where B: Default, { loop {} } - /// Send a constructed `Request` using this `Client`. - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "runtime")] - /// # fn run () { - /// use hyper::{Body, Method, Client, Request}; - /// - /// let client = Client::new(); - /// - /// let req = Request::builder() - /// .method(Method::POST) - /// .uri("http://httpbin.org/post") - /// .body(Body::from("Hallo!")) - /// .expect("request builder"); - /// - /// let future = client.request(req); - /// # } - /// # fn main() {} - /// ``` + + + + + + + + + + + + + + + + + + + + + pub(crate) fn request(&self, mut req: Request) -> ResponseFuture { loop {} } @@ -419,7 +419,7 @@ enum ClientConnectError { Normal(crate::Error), H2CheckoutIsClosed(crate::Error), } -/// A marker to identify what version a pooled connection is. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(super) enum Ver { Auto, @@ -449,25 +449,25 @@ fn get_non_default_port(uri: &Uri) -> Option> { fn is_schema_secure(uri: &Uri) -> bool { loop {} } -/// A builder to configure a new [`Client`](Client). -/// -/// # Example -/// -/// ``` -/// # #[cfg(feature = "runtime")] -/// # fn run () { -/// use std::time::Duration; -/// use hyper::Client; -/// -/// let client = Client::builder() -/// .pool_idle_timeout(Duration::from_secs(30)) -/// .http2_only(true) -/// .build_http(); -/// # let infer: Client<_, hyper::Body> = client; -/// # drop(infer); -/// # } -/// # fn main() {} -/// ``` + + + + + + + + + + + + + + + + + + + #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[derive(Clone)] pub struct Builder { @@ -496,11 +496,11 @@ impl Builder { { loop {} } - /// Set an optional timeout for idle sockets being kept-alive. - /// - /// Pass `None` to disable timeout. - /// - /// Default is 90 seconds. + + + + + pub(crate) fn pool_idle_timeout(&mut self, val: D) -> &mut Self where D: Into>, @@ -512,198 +512,198 @@ impl Builder { pub(crate) fn max_idle_per_host(&mut self, max_idle: usize) -> &mut Self { loop {} } - /// Sets the maximum idle connection per host allowed in the pool. - /// - /// Default is `usize::MAX` (no limit). + + + pub(crate) fn pool_max_idle_per_host(&mut self, max_idle: usize) -> &mut Self { loop {} } - /// Sets the exact size of the read buffer to *always* use. - /// - /// Note that setting this option unsets the `http1_max_buf_size` option. - /// - /// Default is an adaptive read buffer. + + + + + pub(crate) fn http1_read_buf_exact_size(&mut self, sz: usize) -> &mut Self { loop {} } - /// Set the maximum buffer size for the connection. - /// - /// Default is ~400kb. - /// - /// Note that setting this option unsets the `http1_read_exact_buf_size` option. - /// - /// # Panics - /// - /// The minimum value allowed is 8192. This method panics if the passed `max` is less than the minimum. + + + + + + + + + #[cfg(feature = "http1")] #[cfg_attr(docsrs, doc(cfg(feature = "http1")))] pub(crate) fn http1_max_buf_size(&mut self, max: usize) -> &mut Self { loop {} } - /// Set whether HTTP/1 connections will accept spaces between header names - /// and the colon that follow them in responses. - /// - /// Newline codepoints (`\r` and `\n`) will be transformed to spaces when - /// parsing. - /// - /// You probably don't need this, here is what [RFC 7230 Section 3.2.4.] has - /// to say about it: - /// - /// > No whitespace is allowed between the header field-name and colon. In - /// > the past, differences in the handling of such whitespace have led to - /// > security vulnerabilities in request routing and response handling. A - /// > server MUST reject any received request message that contains - /// > whitespace between a header field-name and colon with a response code - /// > of 400 (Bad Request). A proxy MUST remove any such whitespace from a - /// > response message before forwarding the message downstream. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. - /// - /// [RFC 7230 Section 3.2.4.]: https://tools.ietf.org/html/rfc7230#section-3.2.4 + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn http1_allow_spaces_after_header_name_in_responses( &mut self, val: bool, ) -> &mut Self { loop {} } - /// Set whether HTTP/1 connections will accept obsolete line folding for - /// header values. - /// - /// You probably don't need this, here is what [RFC 7230 Section 3.2.4.] has - /// to say about it: - /// - /// > A server that receives an obs-fold in a request message that is not - /// > within a message/http container MUST either reject the message by - /// > sending a 400 (Bad Request), preferably with a representation - /// > explaining that obsolete line folding is unacceptable, or replace - /// > each received obs-fold with one or more SP octets prior to - /// > interpreting the field value or forwarding the message downstream. - /// - /// > A proxy or gateway that receives an obs-fold in a response message - /// > that is not within a message/http container MUST either discard the - /// > message and replace it with a 502 (Bad Gateway) response, preferably - /// > with a representation explaining that unacceptable line folding was - /// > received, or replace each received obs-fold with one or more SP - /// > octets prior to interpreting the field value or forwarding the - /// > message downstream. - /// - /// > A user agent that receives an obs-fold in a response message that is - /// > not within a message/http container MUST replace each received - /// > obs-fold with one or more SP octets prior to interpreting the field - /// > value. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. - /// - /// [RFC 7230 Section 3.2.4.]: https://tools.ietf.org/html/rfc7230#section-3.2.4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn http1_allow_obsolete_multiline_headers_in_responses( &mut self, val: bool, ) -> &mut Self { loop {} } - /// Sets whether invalid header lines should be silently ignored in HTTP/1 responses. - /// - /// This mimicks the behaviour of major browsers. You probably don't want this. - /// You should only want this if you are implementing a proxy whose main - /// purpose is to sit in front of browsers whose users access arbitrary content - /// which may be malformed, and they expect everything that works without - /// the proxy to keep working with the proxy. - /// - /// This option will prevent Hyper's client from returning an error encountered - /// when parsing a header, except if the error was caused by the character NUL - /// (ASCII code 0), as Chrome specifically always reject those. - /// - /// The ignorable errors are: - /// * empty header names; - /// * characters that are not allowed in header names, except for `\0` and `\r`; - /// * when `allow_spaces_after_header_name_in_responses` is not enabled, - /// spaces and tabs between the header name and the colon; - /// * missing colon between header name and colon; - /// * characters that are not allowed in header values except for `\0` and `\r`. - /// - /// If an ignorable error is encountered, the parser tries to find the next - /// line in the input to resume parsing the rest of the headers. An error - /// will be emitted nonetheless if it finds `\0` or a lone `\r` while - /// looking for the next line. + + + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn http1_ignore_invalid_headers_in_responses( &mut self, val: bool, ) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections should try to use vectored writes, - /// or always flatten into a single buffer. - /// - /// Note that setting this to false may mean more copies of body data, - /// but may also improve performance when an IO transport doesn't - /// support vectored writes well, such as most TLS implementations. - /// - /// Setting this to true will force hyper to use queued strategy - /// which may eliminate unnecessary cloning on some TLS backends - /// - /// Default is `auto`. In this mode hyper will try to guess which - /// mode to use + + + + + + + + + + + + pub(crate) fn http1_writev(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections will write header names as title case at - /// the socket level. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + pub(crate) fn http1_title_case_headers(&mut self, val: bool) -> &mut Self { loop {} } - /// Set whether to support preserving original header cases. - /// - /// Currently, this will record the original cases received, and store them - /// in a private extension on the `Response`. It will also look for and use - /// such an extension in any provided `Request`. - /// - /// Since the relevant extension is still private, there is no way to - /// interact with the original cases. The only effect this can have now is - /// to forward the cases in a proxy-like fashion. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + + + + + + + + pub(crate) fn http1_preserve_header_case(&mut self, val: bool) -> &mut Self { loop {} } - /// Set whether HTTP/0.9 responses should be tolerated. - /// - /// Default is false. + + + pub(crate) fn http09_responses(&mut self, val: bool) -> &mut Self { loop {} } - /// Set whether the connection **must** use HTTP/2. - /// - /// The destination must either allow HTTP2 Prior Knowledge, or the - /// `Connect` should be configured to do use ALPN to upgrade to `h2` - /// as part of the connection process. This will not make the `Client` - /// utilize ALPN by itself. - /// - /// Note that setting this to true prevents HTTP/1 from being allowed. - /// - /// Default is false. + + + + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_only(&mut self, val: bool) -> &mut Self { loop {} } - /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 - /// stream-level flow control. - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. - /// - /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_initial_stream_window_size( @@ -712,11 +712,11 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets the max connection-level flow control for HTTP2 - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_initial_connection_window_size( @@ -725,21 +725,21 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets whether to use an adaptive flow control. - /// - /// Enabling this will override the limits set in - /// `http2_initial_stream_window_size` and - /// `http2_initial_connection_window_size`. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_adaptive_window(&mut self, enabled: bool) -> &mut Self { loop {} } - /// Sets the maximum frame size to use for HTTP2. - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_frame_size( @@ -748,16 +748,16 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets an interval for HTTP2 Ping frames should be sent to keep a - /// connection alive. - /// - /// Pass `None` to disable HTTP2 keep-alive. - /// - /// Default is currently disabled. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] @@ -767,48 +767,48 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. Does nothing if `http2_keep_alive_interval` is disabled. - /// - /// Default is 20 seconds. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_keep_alive_timeout(&mut self, timeout: Duration) -> &mut Self { loop {} } - /// Sets whether HTTP2 keep-alive should apply while the connection is idle. - /// - /// If disabled, keep-alive pings are only sent while there are open - /// request/responses streams. If enabled, pings are also sent when no - /// streams are active. Does nothing if `http2_keep_alive_interval` is - /// disabled. - /// - /// Default is `false`. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_keep_alive_while_idle(&mut self, enabled: bool) -> &mut Self { loop {} } - /// Sets the maximum number of HTTP2 concurrent locally reset streams. - /// - /// See the documentation of [`h2::client::Builder::max_concurrent_reset_streams`] for more - /// details. - /// - /// The default value is determined by the `h2` crate. - /// - /// [`h2::client::Builder::max_concurrent_reset_streams`]: https://docs.rs/h2/client/struct.Builder.html#method.max_concurrent_reset_streams + + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_concurrent_reset_streams( @@ -817,51 +817,51 @@ impl Builder { ) -> &mut Self { loop {} } - /// Set the maximum write buffer size for each HTTP/2 stream. - /// - /// Default is currently 1MB, but may change. - /// - /// # Panics - /// - /// The value must be no larger than `u32::MAX`. + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_send_buf_size(&mut self, max: usize) -> &mut Self { loop {} } - /// Set whether to retry requests that get disrupted before ever starting - /// to write. - /// - /// This means a request that is queued, and gets given an idle, reused - /// connection, and then encounters an error immediately as the idle - /// connection was found to be unusable. - /// - /// When this is set to `false`, the related `ResponseFuture` would instead - /// resolve to an `Error::Cancel`. - /// - /// Default is `true`. + + + + + + + + + + + #[inline] pub(crate) fn retry_canceled_requests(&mut self, val: bool) -> &mut Self { loop {} } - /// Set whether to automatically add the `Host` header to requests. - /// - /// If true, and a request does not include a `Host` header, one will be - /// added automatically, derived from the authority of the `Uri`. - /// - /// Default is `true`. + + + + + + #[inline] pub(crate) fn set_host(&mut self, val: bool) -> &mut Self { loop {} } - /// Provide an executor to execute background `Connection` tasks. + pub(crate) fn executor(&mut self, exec: E) -> &mut Self where E: Executor + Send + Sync + 'static, { loop {} } - /// Builder a client with this configuration and the default `HttpConnector`. + #[cfg(feature = "tcp")] pub(crate) fn build_http(&self) -> Client where @@ -870,7 +870,7 @@ impl Builder { { loop {} } - /// Combine the configuration of this builder with a connector to create a `Client`. + pub(crate) fn build(&self, connector: C) -> Client where C: Connect + Clone, diff --git a/hyper/src/client/conn.rs b/hyper/src/client/conn.rs index e64601c..22fb3c2 100644 --- a/hyper/src/client/conn.rs +++ b/hyper/src/client/conn.rs @@ -96,10 +96,10 @@ pin_project! { #[project = ProtoClientProj] enum ProtoClient < T, B > where B : HttpBody, { H1 { #[pin] h1 : Http1Dispatcher < T, B >, }, H2 { #[pin] h2 : Http2ClientTask < B >, }, } } -/// Returns a handshake future over some IO. -/// -/// This is a shortcut for `Builder::new().handshake(io)`. -/// See [`client::conn`](crate::client::conn) for more. + + + + pub(crate) async fn handshake( io: T, ) -> crate::Result<(SendRequest, Connection)> @@ -108,14 +108,14 @@ where { loop {} } -/// The sender side of an established connection. + pub struct SendRequest { dispatch: dispatch::Sender, Response>, } -/// A future that processes all HTTP state for the IO object. -/// -/// In most cases, this should just be spawned into an executor, so that it -/// can process incoming and outgoing messages, notice hangups, and the like. + + + + #[must_use = "futures do nothing unless polled"] pub struct Connection where @@ -124,9 +124,9 @@ where { inner: Option>, } -/// A builder to configure an HTTP connection. -/// -/// After setting options, the builder is used to create a handshake future. + + + #[derive(Clone, Debug)] pub struct Builder { pub(super) exec: Exec, @@ -152,9 +152,9 @@ enum Proto { #[cfg(feature = "http2")] Http2, } -/// A future returned by `SendRequest::send_request`. -/// -/// Yields a `Response` if successful. + + + #[must_use = "futures do nothing unless polled"] pub struct ResponseFuture { inner: ResponseFutureState, @@ -163,22 +163,22 @@ enum ResponseFutureState { Waiting(dispatch::Promise>), Error(Option), } -/// Deconstructed parts of a `Connection`. -/// -/// This allows taking apart a `Connection` at a later time, in order to -/// reclaim the IO object, and additional related pieces. + + + + #[derive(Debug)] pub struct Parts { - /// The original IO object used in the handshake. + pub(crate) io: T, - /// A buffer of bytes that have been read but not processed as HTTP. - /// - /// For instance, if the `Connection` is used for an HTTP upgrade request, - /// it is possible the server sent back the first bytes of the new protocol - /// along with the response upgrade. - /// - /// You will want to check for any existing bytes if you plan to continue - /// communicating on the IO object. + + + + + + + + pub(crate) read_buf: Bytes, _inner: (), } @@ -188,9 +188,9 @@ pub(super) struct Http2SendRequest { dispatch: dispatch::UnboundedSender, Response>, } impl SendRequest { - /// Polls to determine whether this sender can be used yet for a request. - /// - /// If the associated connection is closed, this returns an Error. + + + pub(crate) fn poll_ready( &mut self, cx: &mut task::Context<'_>, @@ -215,47 +215,47 @@ impl SendRequest where B: HttpBody + 'static, { - /// Sends a `Request` on the associated connection. - /// - /// Returns a future that if successful, yields the `Response`. - /// - /// # Note - /// - /// There are some key differences in what automatic things the `Client` - /// does for you that will not be done here: - /// - /// - `Client` requires absolute-form `Uri`s, since the scheme and - /// authority are needed to connect. They aren't required here. - /// - Since the `Client` requires absolute-form `Uri`s, it can add - /// the `Host` header based on it. You must add a `Host` header yourself - /// before calling this method. - /// - Since absolute-form `Uri`s are not required, if received, they will - /// be serialized as-is. - /// - /// # Example - /// - /// ``` - /// # use http::header::HOST; - /// # use hyper::client::conn::SendRequest; - /// # use hyper::Body; - /// use hyper::Request; - /// - /// # async fn doc(mut tx: SendRequest) -> hyper::Result<()> { - /// // build a Request - /// let req = Request::builder() - /// .uri("/foo/bar") - /// .header(HOST, "hyper.rs") - /// .body(Body::empty()) - /// .unwrap(); - /// - /// // send it and await a Response - /// let res = tx.send_request(req).await?; - /// // assert the Response - /// assert!(res.status().is_success()); - /// # Ok(()) - /// # } - /// # fn main() {} - /// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn send_request(&mut self, req: Request) -> ResponseFuture { loop {} } @@ -372,31 +372,31 @@ where B::Data: Send, B::Error: Into>, { - /// Return the inner IO object, and additional information. - /// - /// Only works for HTTP/1 connections. HTTP/2 connections will panic. + + + pub(crate) fn into_parts(self) -> Parts { loop {} } - /// Poll the connection for completion, but without calling `shutdown` - /// on the underlying IO. - /// - /// This is useful to allow running a connection while doing an HTTP - /// upgrade. Once the upgrade is completed, the connection would be "done", - /// but it is not desired to actually shutdown the IO object. Instead you - /// would take it back using `into_parts`. - /// - /// Use [`poll_fn`](https://docs.rs/futures/0.1.25/futures/future/fn.poll_fn.html) - /// and [`try_ready!`](https://docs.rs/futures/0.1.25/futures/macro.try_ready.html) - /// to work with this function; or use the `without_shutdown` wrapper. + + + + + + + + + + + pub(crate) fn poll_without_shutdown( &mut self, cx: &mut task::Context<'_>, ) -> Poll> { loop {} } - /// Prevent shutdown of the underlying IO object at the end of service the request, - /// instead run `into_parts`. This is a convenience wrapper over `poll_without_shutdown`. + + pub(crate) fn without_shutdown( self, ) -> impl Future>> { @@ -406,15 +406,15 @@ where Poll::Ready(Ok(conn.take().unwrap().into_parts())) }) } - /// Returns whether the [extended CONNECT protocol][1] is enabled or not. - /// - /// This setting is configured by the server peer by sending the - /// [`SETTINGS_ENABLE_CONNECT_PROTOCOL` parameter][2] in a `SETTINGS` frame. - /// This method returns the currently acknowledged value received from the - /// remote. - /// - /// [1]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 - /// [2]: https://datatracker.ietf.org/doc/html/rfc8441#section-3 + + + + + + + + + #[cfg(feature = "http2")] pub(crate) fn http2_is_extended_connect_protocol_enabled(&self) -> bool { loop {} @@ -442,177 +442,177 @@ where } } impl Builder { - /// Creates a new connection builder. + #[inline] pub(crate) fn new() -> Builder { loop {} } - /// Provide an executor to execute background HTTP2 tasks. + pub(crate) fn executor(&mut self, exec: E) -> &mut Builder where E: Executor + Send + Sync + 'static, { loop {} } - /// Set whether HTTP/0.9 responses should be tolerated. - /// - /// Default is false. + + + pub(crate) fn http09_responses(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections will accept spaces between header names - /// and the colon that follow them in responses. - /// - /// You probably don't need this, here is what [RFC 7230 Section 3.2.4.] has - /// to say about it: - /// - /// > No whitespace is allowed between the header field-name and colon. In - /// > the past, differences in the handling of such whitespace have led to - /// > security vulnerabilities in request routing and response handling. A - /// > server MUST reject any received request message that contains - /// > whitespace between a header field-name and colon with a response code - /// > of 400 (Bad Request). A proxy MUST remove any such whitespace from a - /// > response message before forwarding the message downstream. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. - /// - /// [RFC 7230 Section 3.2.4.]: https://tools.ietf.org/html/rfc7230#section-3.2.4 + + + + + + + + + + + + + + + + + + + pub(crate) fn http1_allow_spaces_after_header_name_in_responses( &mut self, enabled: bool, ) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections will accept obsolete line folding for - /// header values. - /// - /// Newline codepoints (`\r` and `\n`) will be transformed to spaces when - /// parsing. - /// - /// You probably don't need this, here is what [RFC 7230 Section 3.2.4.] has - /// to say about it: - /// - /// > A server that receives an obs-fold in a request message that is not - /// > within a message/http container MUST either reject the message by - /// > sending a 400 (Bad Request), preferably with a representation - /// > explaining that obsolete line folding is unacceptable, or replace - /// > each received obs-fold with one or more SP octets prior to - /// > interpreting the field value or forwarding the message downstream. - /// - /// > A proxy or gateway that receives an obs-fold in a response message - /// > that is not within a message/http container MUST either discard the - /// > message and replace it with a 502 (Bad Gateway) response, preferably - /// > with a representation explaining that unacceptable line folding was - /// > received, or replace each received obs-fold with one or more SP - /// > octets prior to interpreting the field value or forwarding the - /// > message downstream. - /// - /// > A user agent that receives an obs-fold in a response message that is - /// > not within a message/http container MUST replace each received - /// > obs-fold with one or more SP octets prior to interpreting the field - /// > value. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. - /// - /// [RFC 7230 Section 3.2.4.]: https://tools.ietf.org/html/rfc7230#section-3.2.4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn http1_allow_obsolete_multiline_headers_in_responses( &mut self, enabled: bool, ) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections will silently ignored malformed header lines. - /// - /// If this is enabled and and a header line does not start with a valid header - /// name, or does not include a colon at all, the line will be silently ignored - /// and no error will be reported. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + + + + pub(crate) fn http1_ignore_invalid_headers_in_responses( &mut self, enabled: bool, ) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections should try to use vectored writes, - /// or always flatten into a single buffer. - /// - /// Note that setting this to false may mean more copies of body data, - /// but may also improve performance when an IO transport doesn't - /// support vectored writes well, such as most TLS implementations. - /// - /// Setting this to true will force hyper to use queued strategy - /// which may eliminate unnecessary cloning on some TLS backends - /// - /// Default is `auto`. In this mode hyper will try to guess which - /// mode to use + + + + + + + + + + + + pub(crate) fn http1_writev(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Set whether HTTP/1 connections will write header names as title case at - /// the socket level. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + pub(crate) fn http1_title_case_headers(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Set whether to support preserving original header cases. - /// - /// Currently, this will record the original cases received, and store them - /// in a private extension on the `Response`. It will also look for and use - /// such an extension in any provided `Request`. - /// - /// Since the relevant extension is still private, there is no way to - /// interact with the original cases. The only effect this can have now is - /// to forward the cases in a proxy-like fashion. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + + + + + + + + pub(crate) fn http1_preserve_header_case(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Set whether to support preserving original header order. - /// - /// Currently, this will record the order in which headers are received, and store this - /// ordering in a private extension on the `Response`. It will also look for and use - /// such an extension in any provided `Request`. - /// - /// Note that this setting does not affect HTTP/2. - /// - /// Default is false. + + + + + + + + + #[cfg(feature = "ffi")] pub(crate) fn http1_preserve_header_order(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Sets the exact size of the read buffer to *always* use. - /// - /// Note that setting this option unsets the `http1_max_buf_size` option. - /// - /// Default is an adaptive read buffer. + + + + + pub(crate) fn http1_read_buf_exact_size( &mut self, sz: Option, ) -> &mut Builder { loop {} } - /// Set the maximum buffer size for the connection. - /// - /// Default is ~400kb. - /// - /// Note that setting this option unsets the `http1_read_exact_buf_size` option. - /// - /// # Panics - /// - /// The minimum value allowed is 8192. This method panics if the passed `max` is less than the minimum. + + + + + + + + + #[cfg(feature = "http1")] #[cfg_attr(docsrs, doc(cfg(feature = "http1")))] pub(crate) fn http1_max_buf_size(&mut self, max: usize) -> &mut Self { @@ -622,22 +622,22 @@ impl Builder { pub(crate) fn http1_headers_raw(&mut self, enabled: bool) -> &mut Self { loop {} } - /// Sets whether HTTP2 is required. - /// - /// Default is false. + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_only(&mut self, enabled: bool) -> &mut Builder { loop {} } - /// Sets the [`SETTINGS_INITIAL_WINDOW_SIZE`][spec] option for HTTP2 - /// stream-level flow control. - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. - /// - /// [spec]: https://http2.github.io/http2-spec/#SETTINGS_INITIAL_WINDOW_SIZE + + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_initial_stream_window_size( @@ -646,11 +646,11 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets the max connection-level flow control for HTTP2 - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_initial_connection_window_size( @@ -659,21 +659,21 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets whether to use an adaptive flow control. - /// - /// Enabling this will override the limits set in - /// `http2_initial_stream_window_size` and - /// `http2_initial_connection_window_size`. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_adaptive_window(&mut self, enabled: bool) -> &mut Self { loop {} } - /// Sets the maximum frame size to use for HTTP2. - /// - /// Passing `None` will do nothing. - /// - /// If not set, hyper will use a default. + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_frame_size( @@ -682,16 +682,16 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets an interval for HTTP2 Ping frames should be sent to keep a - /// connection alive. - /// - /// Pass `None` to disable HTTP2 keep-alive. - /// - /// Default is currently disabled. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] @@ -701,48 +701,48 @@ impl Builder { ) -> &mut Self { loop {} } - /// Sets a timeout for receiving an acknowledgement of the keep-alive ping. - /// - /// If the ping is not acknowledged within the timeout, the connection will - /// be closed. Does nothing if `http2_keep_alive_interval` is disabled. - /// - /// Default is 20 seconds. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_keep_alive_timeout(&mut self, timeout: Duration) -> &mut Self { loop {} } - /// Sets whether HTTP2 keep-alive should apply while the connection is idle. - /// - /// If disabled, keep-alive pings are only sent while there are open - /// request/responses streams. If enabled, pings are also sent when no - /// streams are active. Does nothing if `http2_keep_alive_interval` is - /// disabled. - /// - /// Default is `false`. - /// - /// # Cargo Feature - /// - /// Requires the `runtime` cargo feature to be enabled. + + + + + + + + + + + + #[cfg(feature = "runtime")] #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_keep_alive_while_idle(&mut self, enabled: bool) -> &mut Self { loop {} } - /// Sets the maximum number of HTTP2 concurrent locally reset streams. - /// - /// See the documentation of [`h2::client::Builder::max_concurrent_reset_streams`] for more - /// details. - /// - /// The default value is determined by the `h2` crate. - /// - /// [`h2::client::Builder::max_concurrent_reset_streams`]: https://docs.rs/h2/client/struct.Builder.html#method.max_concurrent_reset_streams + + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_concurrent_reset_streams( @@ -751,23 +751,23 @@ impl Builder { ) -> &mut Self { loop {} } - /// Set the maximum write buffer size for each HTTP/2 stream. - /// - /// Default is currently 1MB, but may change. - /// - /// # Panics - /// - /// The value must be no larger than `u32::MAX`. + + + + + + + #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub(crate) fn http2_max_send_buf_size(&mut self, max: usize) -> &mut Self { loop {} } - /// Constructs a connection with the configured options and IO. - /// See [`client::conn`](crate::client::conn) for more. - /// - /// Note, if [`Connection`] is not `await`-ed, [`SendRequest`] will - /// do nothing. + + + + + pub(crate) fn handshake( &self, io: T, diff --git a/hyper/src/client/connect/dns.rs b/hyper/src/client/connect/dns.rs index b2a0da4..6108d25 100644 --- a/hyper/src/client/connect/dns.rs +++ b/hyper/src/client/connect/dns.rs @@ -34,21 +34,21 @@ use tokio::task::JoinHandle; use tower_service::Service; pub(super) use self::sealed::Resolve; -/// A domain name to resolve into IP addresses. + #[derive(Clone, Hash, Eq, PartialEq)] pub struct Name { host: Box, } -/// A resolver using blocking `getaddrinfo` calls in a threadpool. + #[derive(Clone)] pub struct GaiResolver { _priv: (), } -/// An iterator of IP addresses returned from `getaddrinfo`. + pub struct GaiAddrs { inner: SocketAddrs, } -/// A future to resolve a name returned by `GaiResolver`. + pub struct GaiFuture { inner: JoinHandle>, } @@ -56,7 +56,7 @@ impl Name { pub(super) fn new(host: Box) -> Name { loop {} } - /// View the hostname as a string slice. + pub(crate) fn as_str(&self) -> &str { loop {} } @@ -77,7 +77,7 @@ impl FromStr for Name { loop {} } } -/// Error indicating a given string was not a valid domain name. + #[derive(Debug)] pub struct InvalidNameError(()); impl fmt::Display for InvalidNameError { @@ -87,7 +87,7 @@ impl fmt::Display for InvalidNameError { } impl Error for InvalidNameError {} impl GaiResolver { - /// Construct a new `GaiResolver`. + pub(crate) fn new() -> Self { loop {} } diff --git a/hyper/src/client/connect/http.rs b/hyper/src/client/connect/http.rs index c029282..6383fe3 100644 --- a/hyper/src/client/connect/http.rs +++ b/hyper/src/client/connect/http.rs @@ -16,48 +16,48 @@ use tokio::time::Sleep; use tracing::{warn}; use super::dns::{self, GaiResolver, Resolve}; use super::{Connected, Connection}; -/// A connector for the `http` scheme. -/// -/// Performs DNS resolution in a thread pool, and then connects over TCP. -/// -/// # Note -/// -/// Sets the [`HttpInfo`](HttpInfo) value on responses, which includes -/// transport information such as the remote socket address used. + + + + + + + + #[cfg_attr(docsrs, doc(cfg(feature = "tcp")))] #[derive(Clone)] pub struct HttpConnector { config: Arc, resolver: R, } -/// Extra information about the transport when an HttpConnector is used. -/// -/// # Example -/// -/// ``` -/// # async fn doc() -> hyper::Result<()> { -/// use hyper::Uri; -/// use hyper::client::{Client, connect::HttpInfo}; -/// -/// let client = Client::new(); -/// let uri = Uri::from_static("http://example.com"); -/// -/// let res = client.get(uri).await?; -/// res -/// .extensions() -/// .get::() -/// .map(|info| { -/// println!("remote addr = {}", info.remote_addr()); -/// }); -/// # Ok(()) -/// # } -/// ``` -/// -/// # Note -/// -/// If a different connector is used besides [`HttpConnector`](HttpConnector), -/// this value will not exist in the extensions. Consult that specific -/// connector to see what "extra" information it might provide to responses. + + + + + + + + + + + + + + + + + + + + + + + + + + + + #[derive(Clone, Debug)] pub struct HttpInfo { remote_addr: SocketAddr, @@ -77,62 +77,62 @@ struct Config { recv_buffer_size: Option, } impl HttpConnector { - /// Construct a new HttpConnector. + pub(crate) fn new() -> HttpConnector { loop {} } } impl HttpConnector { - /// Construct a new HttpConnector. - /// - /// Takes a [`Resolver`](crate::client::connect::dns#resolvers-are-services) to handle DNS lookups. + + + pub(crate) fn new_with_resolver(resolver: R) -> HttpConnector { loop {} } - /// Option to enforce all `Uri`s have the `http` scheme. - /// - /// Enabled by default. + + + #[inline] pub(crate) fn enforce_http(&mut self, is_enforced: bool) { loop {} } - /// Set that all sockets have `SO_KEEPALIVE` set with the supplied duration. - /// - /// If `None`, the option will not be set. - /// - /// Default is `None`. + + + + + #[inline] pub(crate) fn set_keepalive(&mut self, dur: Option) { loop {} } - /// Set that all sockets have `SO_NODELAY` set to the supplied value `nodelay`. - /// - /// Default is `false`. + + + #[inline] pub(crate) fn set_nodelay(&mut self, nodelay: bool) { loop {} } - /// Sets the value of the SO_SNDBUF option on the socket. + #[inline] pub(crate) fn set_send_buffer_size(&mut self, size: Option) { loop {} } - /// Sets the value of the SO_RCVBUF option on the socket. + #[inline] pub(crate) fn set_recv_buffer_size(&mut self, size: Option) { loop {} } - /// Set that all sockets are bound to the configured address before connection. - /// - /// If `None`, the sockets will not be bound. - /// - /// Default is `None`. + + + + + #[inline] pub(crate) fn set_local_address(&mut self, addr: Option) { loop {} } - /// Set that all sockets are bound to the configured IPv4 or IPv6 address (depending on host's - /// preferences) before connection. + + #[inline] pub(crate) fn set_local_addresses( &mut self, @@ -141,35 +141,35 @@ impl HttpConnector { ) { loop {} } - /// Set the connect timeout. - /// - /// If a domain resolves to multiple IP addresses, the timeout will be - /// evenly divided across them. - /// - /// Default is `None`. + + + + + + #[inline] pub(crate) fn set_connect_timeout(&mut self, dur: Option) { loop {} } - /// Set timeout for [RFC 6555 (Happy Eyeballs)][RFC 6555] algorithm. - /// - /// If hostname resolves to both IPv4 and IPv6 addresses and connection - /// cannot be established using preferred address family before timeout - /// elapses, then connector will in parallel attempt connection using other - /// address family. - /// - /// If `None`, parallel connection attempts are disabled. - /// - /// Default is 300 milliseconds. - /// - /// [RFC 6555]: https://tools.ietf.org/html/rfc6555 + + + + + + + + + + + + #[inline] pub(crate) fn set_happy_eyeballs_timeout(&mut self, dur: Option) { loop {} } - /// Set that all socket have `SO_REUSEADDR` set to the supplied value `reuse_address`. - /// - /// Default is `false`. + + + #[inline] pub(crate) fn set_reuse_address(&mut self, reuse_address: bool) -> &mut Self { loop {} @@ -224,11 +224,11 @@ impl Connection for TcpStream { } } impl HttpInfo { - /// Get the remote address of the transport used. + pub(crate) fn remote_addr(&self) -> SocketAddr { loop {} } - /// Get the local address of the transport used. + pub(crate) fn local_addr(&self) -> SocketAddr { loop {} } diff --git a/hyper/src/client/connect/mod.rs b/hyper/src/client/connect/mod.rs index ebf783f..f4b2eb6 100644 --- a/hyper/src/client/connect/mod.rs +++ b/hyper/src/client/connect/mod.rs @@ -88,15 +88,15 @@ cfg_feature! { cfg_feature! { #![any(feature = "http1", feature = "http2")] pub use self::sealed::Connect; } -/// Describes a type returned by a connector. + pub trait Connection { - /// Return metadata describing the connection. + fn connected(&self) -> Connected; } -/// Extra information about the connected transport. -/// -/// This can be used to inform recipients about things like if ALPN -/// was used, or if connected to an HTTP proxy. + + + + #[derive(Debug)] pub struct Connected { pub(super) alpn: Alpn, @@ -110,51 +110,51 @@ pub(super) enum Alpn { None, } impl Connected { - /// Create new `Connected` type with empty metadata. + pub(crate) fn new() -> Connected { loop {} } - /// Set whether the connected transport is to an HTTP proxy. - /// - /// This setting will affect if HTTP/1 requests written on the transport - /// will have the request-target in absolute-form or origin-form: - /// - /// - When `proxy(false)`: - /// - /// ```http - /// GET /guide HTTP/1.1 - /// ``` - /// - /// - When `proxy(true)`: - /// - /// ```http - /// GET http://hyper.rs/guide HTTP/1.1 - /// ``` - /// - /// Default is `false`. + + + + + + + + + + + + + + + + + + pub(crate) fn proxy(mut self, is_proxied: bool) -> Connected { loop {} } - /// Determines if the connected transport is to an HTTP proxy. + pub(crate) fn is_proxied(&self) -> bool { loop {} } - /// Set extra connection information to be set in the extensions of every `Response`. + pub(crate) fn extra( mut self, extra: T, ) -> Connected { loop {} } - /// Copies the extra connection information into an `Extensions` map. + pub(crate) fn get_extras(&self, extensions: &mut Extensions) { loop {} } - /// Set that the connected transport negotiated HTTP/2 as its next protocol. + pub(crate) fn negotiated_h2(mut self) -> Connected { loop {} } - /// Determines if the connected transport negotiated HTTP/2 as its next protocol. + pub(crate) fn is_negotiated_h2(&self) -> bool { loop {} } @@ -219,16 +219,16 @@ pub(super) mod sealed { use tokio::io::{AsyncRead, AsyncWrite}; use super::Connection; use crate::common::{Future, Unpin}; - /// Connect to a destination, returning an IO transport. - /// - /// A connector receives a [`Uri`](::http::Uri) and returns a `Future` of the - /// ready connection. - /// - /// # Trait Alias - /// - /// This is really just an *alias* for the `tower::Service` trait, with - /// additional bounds set for convenience *inside* hyper. You don't actually - /// implement this trait, but `tower::Service` instead. + + + + + + + + + + pub trait Connect: Sealed + Sized { #[doc(hidden)] type _Svc: ConnectSvc; diff --git a/hyper/src/client/dispatch.rs b/hyper/src/client/dispatch.rs index cd1742c..2ce0360 100644 --- a/hyper/src/client/dispatch.rs +++ b/hyper/src/client/dispatch.rs @@ -11,30 +11,30 @@ pub(crate) type Promise = oneshot::Receiver>; pub(crate) fn channel() -> (Sender, Receiver) { loop {} } -/// A bounded sender of requests and callbacks for when responses are ready. -/// -/// While the inner sender is unbounded, the Giver is used to determine -/// if the Receiver is ready for another request. + + + + pub(crate) struct Sender { - /// One message is always allowed, even if the Receiver hasn't asked - /// for it yet. This boolean keeps track of whether we've sent one - /// without notice. + + + buffered_once: bool, - /// The Giver helps watch that the the Receiver side has been polled - /// when the queue is empty. This helps us know when a request and - /// response have been fully processed, and a connection is ready - /// for more. + + + + giver: want::Giver, - /// Actually bounded by the Giver, plus `buffered_once`. + inner: mpsc::UnboundedSender>, } -/// An unbounded version. -/// -/// Cannot poll the Giver, but can still use it to determine if the Receiver -/// has been dropped. However, this version can be cloned. + + + + #[cfg(feature = "http2")] pub(crate) struct UnboundedSender { - /// Only used for `is_closed`, since mpsc::UnboundedSender cannot be checked. + giver: want::SharedGiver, inner: mpsc::UnboundedSender>, } @@ -158,7 +158,7 @@ mod tests { loop {} } } - /// Helper to check if the future is ready after polling once. + struct PollOnce<'a, F>(&'a mut F); impl Future for PollOnce<'_, F> where diff --git a/hyper/src/client/pool.rs b/hyper/src/client/pool.rs index 964c859..2b8ad66 100644 --- a/hyper/src/client/pool.rs +++ b/hyper/src/client/pool.rs @@ -17,29 +17,29 @@ pub(super) struct Pool { } pub(super) trait Poolable: Unpin + Send + Sized + 'static { fn is_open(&self) -> bool; - /// Reserve this connection. - /// - /// Allows for HTTP/2 to return a shared reservation. + + + fn reserve(self) -> Reservation; fn can_share(&self) -> bool; } -/// When checking out a pooled connection, it might be that the connection -/// only supports a single reservation, or it might be usable for many. -/// -/// Specifically, HTTP/1 requires a unique reservation, but HTTP/2 can be -/// used for multiple requests. + + + + + #[allow(missing_debug_implementations)] pub(super) enum Reservation { - /// This connection could be used multiple times, the first one will be - /// reinserted into the `idle` pool, and the second will be given to - /// the `Checkout`. + + + #[cfg(feature = "http2")] Shared(T, T), - /// This connection requires unique access. It will be returned after - /// use is complete. + + Unique(T), } -/// Simple type alias in case the key type needs to be adjusted. + pub(super) type Key = (http::uri::Scheme, http::uri::Authority); struct PoolInner { connecting: HashSet, @@ -76,13 +76,13 @@ impl Pool { } } impl Pool { - /// Returns a `Checkout` which is a future that resolves if an idle - /// connection becomes available. + + pub(super) fn checkout(&self, key: Key) -> Checkout { loop {} } - /// Ensure that there is only ever 1 connecting task for HTTP/2 - /// connections. This does nothing for HTTP/1. + + pub(super) fn connecting(&self, key: &Key, ver: Ver) -> Option> { loop {} } @@ -102,7 +102,7 @@ impl Pool { loop {} } } -/// Pop off this list, looking for a usable connection that hasn't expired. + struct IdlePopper<'a, T> { key: &'a Key, list: &'a mut Vec>, @@ -116,8 +116,8 @@ impl PoolInner { fn put(&mut self, key: Key, value: T, __pool_ref: &Arc>>) { loop {} } - /// A `Connecting` task is complete. Not necessarily successfully, - /// but the lock is going away, so clean up. + + fn connected(&mut self, key: &Key) { loop {} } @@ -127,17 +127,17 @@ impl PoolInner { } } impl PoolInner { - /// Any `FutureResponse`s that were created will have made a `Checkout`, - /// and possibly inserted into the pool that it is waiting for an idle - /// connection. If a user ever dropped that future, we need to clean out - /// those parked senders. + + + + fn clean_waiters(&mut self, key: &Key) { loop {} } } #[cfg(feature = "runtime")] impl PoolInner { - /// This should *only* be called by the IdleTask + fn clear_expired(&mut self) { loop {} } @@ -147,7 +147,7 @@ impl Clone for Pool { loop {} } } -/// A wrapped poolable value that tries to reinsert to the Pool on Drop. + pub(super) struct Pooled { value: Option, is_reused: bool, @@ -283,7 +283,7 @@ mod tests { use std::time::Duration; use super::{Connecting, Key, Pool, Poolable, Reservation, WeakOpt}; use crate::common::{exec::Exec, task, Future, Pin}; - /// Test unique reservations. + #[derive(Debug, PartialEq, Eq)] struct Uniq(T); impl Poolable for Uniq { @@ -313,7 +313,7 @@ mod tests { async fn test_pool_checkout_smoke() { loop {} } - /// Helper to check if the future is ready after polling once. + struct PollOnce<'a, F>(&'a mut F); impl Future for PollOnce<'_, F> where diff --git a/hyper/src/client/service.rs b/hyper/src/client/service.rs index 330d97b..87a3c2f 100644 --- a/hyper/src/client/service.rs +++ b/hyper/src/client/service.rs @@ -10,11 +10,11 @@ use crate::{ body::HttpBody, common::{task, Pin, Poll}, service::{MakeConnection, Service}, }; -/// Creates a connection via `SendRequest`. -/// -/// This accepts a `hyper::client::conn::Builder` and provides -/// a `MakeService` implementation to create connections from some -/// target `T`. + + + + + #[derive(Debug)] pub(crate) struct Connect { inner: C, @@ -22,8 +22,8 @@ pub(crate) struct Connect { _pd: PhantomData, } impl Connect { - /// Create a new `Connect` with some inner connector `C` and a connection - /// builder. + + pub(crate) fn new(inner: C, builder: Builder) -> Self { loop {} } diff --git a/hyper/src/common/io/rewind.rs b/hyper/src/common/io/rewind.rs index e02d45c..c621c5e 100644 --- a/hyper/src/common/io/rewind.rs +++ b/hyper/src/common/io/rewind.rs @@ -3,7 +3,7 @@ use std::{io}; use bytes::{Bytes}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::common::{task, Pin, Poll}; -/// Combine a buffer with an IO, rewinding reads to use the buffer. + #[derive(Debug)] pub(crate) struct Rewind { pre: Option, diff --git a/hyper/src/common/sync_wrapper.rs b/hyper/src/common/sync_wrapper.rs index 0c51ddb..defb5e5 100644 --- a/hyper/src/common/sync_wrapper.rs +++ b/hyper/src/common/sync_wrapper.rs @@ -1,97 +1,97 @@ -/// A mutual exclusion primitive that relies on static type information only -/// -/// In some cases synchronization can be proven statically: whenever you hold an exclusive `&mut` -/// reference, the Rust type system ensures that no other part of the program can hold another -/// reference to the data. Therefore it is safe to access it even if the current thread obtained -/// this reference via a channel. Whenever this is the case, the overhead of allocating and locking -/// a [`Mutex`] can be avoided by using this static version. -/// -/// One example where this is often applicable is [`Future`], which requires an exclusive reference -/// for its [`poll`] method: While a given `Future` implementation may not be safe to access by -/// multiple threads concurrently, the executor can only run the `Future` on one thread at any -/// given time, making it [`Sync`] in practice as long as the implementation is `Send`. You can -/// therefore use the sync wrapper to prove that your data structure is `Sync` even though it -/// contains such a `Future`. -/// -/// # Example -/// -/// ```ignore -/// use hyper::common::sync_wrapper::SyncWrapper; -/// use std::future::Future; -/// -/// struct MyThing { -/// future: SyncWrapper + Send>>, -/// } -/// -/// impl MyThing { -/// // all accesses to `self.future` now require an exclusive reference or ownership -/// } -/// -/// fn assert_sync() {} -/// -/// assert_sync::(); -/// ``` -/// -/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html -/// [`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html -/// [`poll`]: https://doc.rust-lang.org/std/future/trait.Future.html#method.poll -/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #[repr(transparent)] pub(crate) struct SyncWrapper(T); impl SyncWrapper { - /// Creates a new SyncWrapper containing the given value. - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let wrapped = SyncWrapper::new(42); - /// ``` + + + + + + + + + pub(crate) fn new(value: T) -> Self { loop {} } - /// Acquires a reference to the protected value. - /// - /// This is safe because it requires an exclusive reference to the wrapper. Therefore this method - /// neither panics nor does it return an error. This is in contrast to [`Mutex::get_mut`] which - /// returns an error if another thread panicked while holding the lock. It is not recommended - /// to send an exclusive reference to a potentially damaged value to another thread for further - /// processing. - /// - /// [`Mutex::get_mut`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.get_mut - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let mut wrapped = SyncWrapper::new(42); - /// let value = wrapped.get_mut(); - /// *value = 0; - /// assert_eq!(*wrapped.get_mut(), 0); - /// ``` + + + + + + + + + + + + + + + + + + + + pub(crate) fn get_mut(&mut self) -> &mut T { loop {} } - /// Consumes this wrapper, returning the underlying data. - /// - /// This is safe because it requires ownership of the wrapper, aherefore this method will neither - /// panic nor does it return an error. This is in contrast to [`Mutex::into_inner`] which - /// returns an error if another thread panicked while holding the lock. It is not recommended - /// to send an exclusive reference to a potentially damaged value to another thread for further - /// processing. - /// - /// [`Mutex::into_inner`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#method.into_inner - /// - /// # Examples - /// - /// ```ignore - /// use hyper::common::sync_wrapper::SyncWrapper; - /// - /// let mut wrapped = SyncWrapper::new(42); - /// assert_eq!(wrapped.into_inner(), 42); - /// ``` + + + + + + + + + + + + + + + + + + #[allow(dead_code)] pub(crate) fn into_inner(self) -> T { loop {} diff --git a/hyper/src/common/task.rs b/hyper/src/common/task.rs index e7e477c..976f1ac 100644 --- a/hyper/src/common/task.rs +++ b/hyper/src/common/task.rs @@ -1,9 +1,9 @@ #[cfg(feature = "http1")] use super::Never; pub(crate) use std::task::{Context, Poll}; -/// A function to help "yield" a future, such that it is re-scheduled immediately. -/// -/// Useful for spin counts, so a future doesn't hog too much time. + + + #[cfg(feature = "http1")] pub(crate) fn yield_now(cx: &mut Context<'_>) -> Poll { loop {} diff --git a/hyper/src/error.rs b/hyper/src/error.rs index f109101..1c7c9cb 100644 --- a/hyper/src/error.rs +++ b/hyper/src/error.rs @@ -1,10 +1,10 @@ //! Error and Result module. use std::error::Error as StdError; use std::fmt; -/// Result type often returned from methods that can have hyper `Error`s. + pub type Result = std::result::Result; type Cause = Box; -/// Represents errors that can occur handling HTTP streams. + pub struct Error { inner: Box, } @@ -16,42 +16,42 @@ struct ErrorImpl { pub(super) enum Kind { Parse(Parse), User(User), - /// A message reached EOF, but is not complete. + #[allow(unused)] IncompleteMessage, - /// A connection received a message (or bytes) when not waiting for one. + #[cfg(feature = "http1")] UnexpectedMessage, - /// A pending item was dropped before ever being processed. + Canceled, - /// Indicates a channel (client or body sender) is closed. + ChannelClosed, - /// An `io::Error` that occurred while trying to read or write to a network stream. + #[cfg(any(feature = "http1", feature = "http2"))] Io, - /// Error occurred while connecting. + #[allow(unused)] Connect, - /// Error creating a TcpListener. + #[cfg(all(feature = "tcp", feature = "server"))] Listen, - /// Error accepting on an Incoming stream. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "server")] Accept, - /// User took too long to send headers + #[cfg(all(feature = "http1", feature = "server", feature = "runtime"))] HeaderTimeout, - /// Error while reading a body from connection. + #[cfg(any(feature = "http1", feature = "http2", feature = "stream"))] Body, - /// Error while writing a body to connection. + #[cfg(any(feature = "http1", feature = "http2"))] BodyWrite, - /// Error calling AsyncWrite::shutdown() + #[cfg(feature = "http1")] Shutdown, - /// A general error from h2. + #[cfg(feature = "http2")] Http2, } @@ -82,100 +82,100 @@ pub(super) enum Header { } #[derive(Debug)] pub(super) enum User { - /// Error calling user's HttpBody::poll_data(). + #[cfg(any(feature = "http1", feature = "http2"))] Body, - /// The user aborted writing of the outgoing body. + BodyWriteAborted, - /// Error calling user's MakeService. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "server")] MakeService, - /// Error from future of user's Service. + #[cfg(any(feature = "http1", feature = "http2"))] Service, - /// User tried to send a certain header in an unexpected context. - /// - /// For example, sending both `content-length` and `transfer-encoding`. + + + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "server")] UnexpectedHeader, - /// User tried to create a Request with bad version. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "client")] UnsupportedVersion, - /// User tried to create a CONNECT Request with the Client. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "client")] UnsupportedRequestMethod, - /// User tried to respond with a 1xx (not 101) response code. + #[cfg(feature = "http1")] #[cfg(feature = "server")] UnsupportedStatusCode, - /// User tried to send a Request with Client with non-absolute URI. + #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "client")] AbsoluteUriRequired, - /// User tried polling for an upgrade that doesn't exist. + NoUpgrade, - /// User polled for an upgrade, but low-level API is not using upgrades. + #[cfg(feature = "http1")] ManualUpgrade, - /// User called `server::Connection::without_shutdown()` on an HTTP/2 conn. + #[cfg(feature = "server")] WithoutShutdownNonHttp1, - /// The dispatch task is gone. + #[cfg(feature = "client")] DispatchGone, - /// User aborted in an FFI callback. + #[cfg(feature = "ffi")] AbortedByCallback, } #[derive(Debug)] pub(super) struct TimedOut; impl Error { - /// Returns true if this was an HTTP parse error. + pub(crate) fn is_parse(&self) -> bool { loop {} } - /// Returns true if this was an HTTP parse error caused by a message that was too large. + pub(crate) fn is_parse_too_large(&self) -> bool { loop {} } - /// Returns true if this was an HTTP parse error caused by an invalid response status code or - /// reason phrase. + + pub(crate) fn is_parse_status(&self) -> bool { loop {} } - /// Returns true if this error was caused by user code. + pub(crate) fn is_user(&self) -> bool { loop {} } - /// Returns true if this was about a `Request` that was canceled. + pub(crate) fn is_canceled(&self) -> bool { loop {} } - /// Returns true if a sender's channel is closed. + pub(crate) fn is_closed(&self) -> bool { loop {} } - /// Returns true if this was an error from `Connect`. + pub(crate) fn is_connect(&self) -> bool { loop {} } - /// Returns true if the connection closed before a message could complete. + pub(crate) fn is_incomplete_message(&self) -> bool { loop {} } - /// Returns true if the body write was aborted. + pub(crate) fn is_body_write_aborted(&self) -> bool { loop {} } - /// Returns true if the error was caused by a timeout. + pub(crate) fn is_timeout(&self) -> bool { loop {} } - /// Consumes the error, returning its cause. + pub(crate) fn into_cause(self) -> Option> { loop {} } @@ -319,7 +319,7 @@ impl Error { pub(super) fn new_h2(cause: ::h2::Error) -> Error { loop {} } - /// The error's standalone message, without the message from the source. + pub(crate) fn message(&self) -> impl fmt::Display + '_ { self.description() } diff --git a/hyper/src/ext.rs b/hyper/src/ext.rs index c0ca6fe..b7febdf 100644 --- a/hyper/src/ext.rs +++ b/hyper/src/ext.rs @@ -13,21 +13,21 @@ use std::fmt; mod h1_reason_phrase; #[cfg(feature = "http2")] -/// Represents the `:protocol` pseudo-header used by -/// the [Extended CONNECT Protocol]. -/// -/// [Extended CONNECT Protocol]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 + + + + #[derive(Clone, Eq, PartialEq)] pub(crate) struct Protocol { inner: h2::ext::Protocol, } #[cfg(feature = "http2")] impl Protocol { - /// Converts a static string to a protocol name. + pub(crate) const fn from_static(value: &'static str) -> Self { loop {} } - /// Returns a str representation of the header. + pub(crate) fn as_str(&self) -> &str { loop {} } @@ -57,41 +57,41 @@ impl fmt::Debug for Protocol { loop {} } } -/// A map from header names to their original casing as received in an HTTP message. -/// -/// If an HTTP/1 response `res` is parsed on a connection whose option -/// [`http1_preserve_header_case`] was set to true and the response included -/// the following headers: -/// -/// ```ignore -/// x-Bread: Baguette -/// X-BREAD: Pain -/// x-bread: Ficelle -/// ``` -/// -/// Then `res.extensions().get::()` will return a map with: -/// -/// ```ignore -/// HeaderCaseMap({ -/// "x-bread": ["x-Bread", "X-BREAD", "x-bread"], -/// }) -/// ``` -/// -/// [`http1_preserve_header_case`]: /client/struct.Client.html#method.http1_preserve_header_case + + + + + + + + + + + + + + + + + + + + + #[derive(Clone, Debug)] pub(crate) struct HeaderCaseMap(HeaderMap); #[cfg(feature = "http1")] impl HeaderCaseMap { - /// Returns a view of all spellings associated with that header name, - /// in the order they were found. + + pub(crate) fn get_all<'a>( &'a self, name: &HeaderName, ) -> impl Iterator + 'a> + 'a { self.get_all_internal(name).into_iter() } - /// Returns a view of all spellings associated with that header name, - /// in the order they were found. + + pub(crate) fn get_all_internal<'a>( &'a self, name: &HeaderName, @@ -114,16 +114,16 @@ impl HeaderCaseMap { } #[cfg(feature = "ffi")] #[derive(Clone, Debug)] -/// Hashmap + pub(crate) struct OriginalHeaderOrder { - /// Stores how many entries a Headername maps to. This is used - /// for accounting. + + num_entries: HashMap, - /// Stores the ordering of the headers. ex: `vec[i] = (headerName, idx)`, - /// The vector is ordered such that the ith element - /// represents the ith header that came in off the line. - /// The `HeaderName` and `idx` are then used elsewhere to index into - /// the multi map that stores the header values. + + + + + entry_order: Vec<(HeaderName, usize)>, } #[cfg(all(feature = "http1", feature = "ffi"))] @@ -140,43 +140,43 @@ impl OriginalHeaderOrder { { loop {} } - /// This returns an iterator that provides header names and indexes - /// in the original order received. - /// - /// # Examples - /// ```no_run - /// use hyper::ext::OriginalHeaderOrder; - /// use hyper::header::{HeaderName, HeaderValue, HeaderMap}; - /// - /// let mut h_order = OriginalHeaderOrder::default(); - /// let mut h_map = Headermap::new(); - /// - /// let name1 = b"Set-CookiE"; - /// let value1 = b"a=b"; - /// h_map.append(name1); - /// h_order.append(name1); - /// - /// let name2 = b"Content-Encoding"; - /// let value2 = b"gzip"; - /// h_map.append(name2, value2); - /// h_order.append(name2); - /// - /// let name3 = b"SET-COOKIE"; - /// let value3 = b"c=d"; - /// h_map.append(name3, value3); - /// h_order.append(name3) - /// - /// let mut iter = h_order.get_in_order() - /// - /// let (name, idx) = iter.next(); - /// assert_eq!(b"a=b", h_map.get_all(name).nth(idx).unwrap()); - /// - /// let (name, idx) = iter.next(); - /// assert_eq!(b"gzip", h_map.get_all(name).nth(idx).unwrap()); - /// - /// let (name, idx) = iter.next(); - /// assert_eq!(b"c=d", h_map.get_all(name).nth(idx).unwrap()); - /// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub(crate) fn get_in_order(&self) -> impl Iterator { loop {} } diff --git a/hyper/src/ffi/body.rs b/hyper/src/ffi/body.rs index f221afa..358ab6b 100644 --- a/hyper/src/ffi/body.rs +++ b/hyper/src/ffi/body.rs @@ -7,9 +7,9 @@ use libc::{c_int, size_t}; use super::task::{hyper_context, hyper_task, hyper_task_return_type, AsTaskType}; use super::{UserDataPointer, HYPER_ITER_CONTINUE}; use crate::body::{Body, Bytes, HttpBody as _}; -/// A streaming HTTP body. + pub(crate) struct hyper_body(pub(super) Body); -/// A buffer of bytes that is sent or received on a `hyper_body`. + pub(crate) struct hyper_buf(pub(crate) Bytes); pub(crate) struct UserBody { data_func: hyper_body_data_callback, @@ -101,7 +101,7 @@ impl UserBody { loop {} } } -/// cbindgen:ignore + extern "C" fn data_noop( _userdata: *mut c_void, _: *mut hyper_context<'_>, diff --git a/hyper/src/ffi/client.rs b/hyper/src/ffi/client.rs index 5126848..27d1330 100644 --- a/hyper/src/ffi/client.rs +++ b/hyper/src/ffi/client.rs @@ -9,17 +9,17 @@ use super::io::hyper_io; use super::task::{ hyper_executor, hyper_task, hyper_task_return_type, AsTaskType, WeakExec, }; -/// An options builder to configure an HTTP client connection. + pub(crate) struct hyper_clientconn_options { builder: conn::Builder, - /// Use a `Weak` to prevent cycles. + exec: WeakExec, } -/// An HTTP client connection handle. -/// -/// These are used to send a request on a single connection. It's possible to -/// send multiple requests on a single connection, such as when HTTP/1 -/// keep-alive or HTTP/2 is used. + + + + + pub(crate) struct hyper_clientconn { tx: conn::SendRequest, } diff --git a/hyper/src/ffi/error.rs b/hyper/src/ffi/error.rs index bd5dfe2..e615f9f 100644 --- a/hyper/src/ffi/error.rs +++ b/hyper/src/ffi/error.rs @@ -1,26 +1,26 @@ use libc::size_t; -/// A more detailed error object returned by some hyper functions. + pub(crate) struct hyper_error(crate::Error); -/// A return code for many of hyper's methods. + #[repr(C)] pub(crate) enum hyper_code { - /// All is well. + HYPERE_OK, - /// General error, details in the `hyper_error *`. + HYPERE_ERROR, - /// A function argument was invalid. + HYPERE_INVALID_ARG, - /// The IO transport returned an EOF when one wasn't expected. - /// - /// This typically means an HTTP request or response was expected, but the - /// connection closed cleanly without sending (all of) it. + + + + HYPERE_UNEXPECTED_EOF, - /// Aborted by a user supplied callback. + HYPERE_ABORTED_BY_CALLBACK, - /// An optional hyper feature was not enabled. + #[cfg_attr(feature = "http2", allow(unused))] HYPERE_FEATURE_NOT_ENABLED, - /// The peer sent an HTTP message that could not be parsed. + HYPERE_INVALID_PEER_MESSAGE, } impl hyper_error { diff --git a/hyper/src/ffi/http_types.rs b/hyper/src/ffi/http_types.rs index 426c7d0..9f86a33 100644 --- a/hyper/src/ffi/http_types.rs +++ b/hyper/src/ffi/http_types.rs @@ -8,13 +8,13 @@ use super::{UserDataPointer, HYPER_ITER_CONTINUE}; use crate::ext::{HeaderCaseMap, OriginalHeaderOrder, ReasonPhrase}; use crate::header::{HeaderName, HeaderValue}; use crate::{Body, HeaderMap, Method, Request, Response, Uri}; -/// An HTTP request. + pub(crate) struct hyper_request(pub(super) Request); -/// An HTTP response. + pub(crate) struct hyper_response(pub(super) Response); -/// An HTTP header map. -/// -/// These can be part of a request or response. + + + pub(crate) struct hyper_headers { pub(super) headers: HeaderMap, orig_casing: HeaderCaseMap, diff --git a/hyper/src/ffi/io.rs b/hyper/src/ffi/io.rs index 886a2a9..c0a978a 100644 --- a/hyper/src/ffi/io.rs +++ b/hyper/src/ffi/io.rs @@ -4,11 +4,11 @@ use std::task::{Context, Poll}; use libc::size_t; use tokio::io::{AsyncRead, AsyncWrite}; use super::task::hyper_context; -/// Sentinel value to return from a read or write callback that the operation -/// is pending. + + pub(crate) const HYPER_IO_PENDING: size_t = 0xFFFFFFFF; -/// Sentinel value to return from a read or write callback that the operation -/// has errored. + + pub(crate) const HYPER_IO_ERROR: size_t = 0xFFFFFFFE; type hyper_io_read_callback = extern "C" fn( *mut c_void, @@ -22,7 +22,7 @@ type hyper_io_write_callback = extern "C" fn( *const u8, size_t, ) -> size_t; -/// An IO object used to represent a socket or similar concept. + pub(crate) struct hyper_io { read: hyper_io_read_callback, write: hyper_io_write_callback, @@ -77,7 +77,7 @@ ffi_fn! { " should be the return value."] fn hyper_io_set_write(io : * mut hyper_io, func : hyper_io_write_callback) { non_null!(& mut * io ?= ()) .write = func; } } -/// cbindgen:ignore + extern "C" fn read_noop( _userdata: *mut c_void, _: *mut hyper_context<'_>, @@ -86,7 +86,7 @@ extern "C" fn read_noop( ) -> size_t { loop {} } -/// cbindgen:ignore + extern "C" fn write_noop( _userdata: *mut c_void, _: *mut hyper_context<'_>, diff --git a/hyper/src/ffi/mod.rs b/hyper/src/ffi/mod.rs index 9b15efa..49ed9a1 100644 --- a/hyper/src/ffi/mod.rs +++ b/hyper/src/ffi/mod.rs @@ -48,23 +48,23 @@ pub(crate) use self::error::*; pub(crate) use self::http_types::*; pub(crate) use self::io::*; pub(crate) use self::task::*; -/// Return in iter functions to continue iterating. + pub(crate) const HYPER_ITER_CONTINUE: libc::c_int = 0; -/// Return in iter functions to stop iterating. + #[allow(unused)] pub(crate) const HYPER_ITER_BREAK: libc::c_int = 1; -/// An HTTP Version that is unspecified. + pub(crate) const HYPER_HTTP_VERSION_NONE: libc::c_int = 0; -/// The HTTP/1.0 version. + pub(crate) const HYPER_HTTP_VERSION_1_0: libc::c_int = 10; -/// The HTTP/1.1 version. + pub(crate) const HYPER_HTTP_VERSION_1_1: libc::c_int = 11; -/// The HTTP/2 version. + pub(crate) const HYPER_HTTP_VERSION_2: libc::c_int = 20; struct UserDataPointer(*mut std::ffi::c_void); unsafe impl Send for UserDataPointer {} unsafe impl Sync for UserDataPointer {} -/// cbindgen:ignore + static VERSION_CSTR: &str = concat!(env!("CARGO_PKG_VERSION"), "\0"); ffi_fn! { #[doc = " Returns a static ASCII (null terminated) string of the hyper version."] fn diff --git a/hyper/src/ffi/task.rs b/hyper/src/ffi/task.rs index eaa8fe7..ea8f0f3 100644 --- a/hyper/src/ffi/task.rs +++ b/hyper/src/ffi/task.rs @@ -13,38 +13,38 @@ use super::error::hyper_code; use super::UserDataPointer; type BoxFuture = Pin + Send>>; type BoxAny = Box; -/// Return in a poll function to indicate it was ready. + pub(crate) const HYPER_POLL_READY: c_int = 0; -/// Return in a poll function to indicate it is still pending. -/// -/// The passed in `hyper_waker` should be registered to wake up the task at -/// some later point. + + + + pub(crate) const HYPER_POLL_PENDING: c_int = 1; -/// Return in a poll function indicate an error. + pub(crate) const HYPER_POLL_ERROR: c_int = 3; -/// A task executor for `hyper_task`s. + pub(crate) struct hyper_executor { - /// The executor of all task futures. - /// - /// There should never be contention on the mutex, as it is only locked - /// to drive the futures. However, we cannot guarantee proper usage from - /// `hyper_executor_poll()`, which in C could potentially be called inside - /// one of the stored futures. The mutex isn't re-entrant, so doing so - /// would result in a deadlock, but that's better than data corruption. + + + + + + + driver: Mutex>, - /// The queue of futures that need to be pushed into the `driver`. - /// - /// This is has a separate mutex since `spawn` could be called from inside - /// a future, which would mean the driver's mutex is already locked. + + + + spawn_queue: Mutex>, - /// This is used to track when a future calls `wake` while we are within - /// `hyper_executor::poll_next`. + + is_woken: Arc, } #[derive(Clone)] pub(crate) struct WeakExec(Weak); struct ExecWaker(AtomicBool); -/// An async task. + pub(crate) struct hyper_task { future: BoxFuture, output: Option, @@ -53,24 +53,24 @@ pub(crate) struct hyper_task { struct TaskFuture { task: Option>, } -/// An async context for a task that contains the related waker. + pub(crate) struct hyper_context<'a>(Context<'a>); -/// A waker that is saved and used to waken a pending task. + pub(crate) struct hyper_waker { waker: std::task::Waker, } -/// A descriptor for what type a `hyper_task` value is. + #[repr(C)] pub(crate) enum hyper_task_return_type { - /// The value of this task is null (does not imply an error). + HYPER_TASK_EMPTY, - /// The value of this task is `hyper_error *`. + HYPER_TASK_ERROR, - /// The value of this task is `hyper_clientconn *`. + HYPER_TASK_CLIENTCONN, - /// The value of this task is `hyper_response *`. + HYPER_TASK_RESPONSE, - /// The value of this task is `hyper_buf *`. + HYPER_TASK_BUF, } pub(crate) unsafe trait AsTaskType { diff --git a/hyper/src/proto/h1/conn.rs b/hyper/src/proto/h1/conn.rs index 278e741..55bd343 100644 --- a/hyper/src/proto/h1/conn.rs +++ b/hyper/src/proto/h1/conn.rs @@ -18,13 +18,13 @@ use crate::common::{task, Poll, Unpin}; use crate::proto::{BodyLength, MessageHead}; const H2_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; -/// This handles a connection, which will have been established over an -/// `AsyncRead + AsyncWrite` (like a socket), and will likely include multiple -/// `Transaction`s over HTTP. -/// -/// The connection will determine when a message begins and ends as well as -/// determine if this connection can be kept alive after the message, -/// or if it is complete. + + + + + + + pub(crate) struct Conn { io: Buffered>, state: State, @@ -217,7 +217,7 @@ where ) -> Poll> { loop {} } - /// If the read side can be cheaply drained, do so. Otherwise, close. + pub(super) fn poll_drain_or_close_read(&mut self, cx: &mut task::Context<'_>) { loop {} } @@ -246,17 +246,17 @@ impl fmt::Debug for Conn { impl Unpin for Conn {} struct State { allow_half_close: bool, - /// Re-usable HeaderMap to reduce allocating new ones. + cached_headers: Option, - /// If an error occurs when there wasn't a direct way to return it - /// back to the user, this is set. + + error: Option, - /// Current keep-alive status. + keep_alive: KA, - /// If mid-message, the HTTP Method that started it. - /// - /// This is used to know things such as if the message can include - /// a body or not. + + + + method: Option, h1_parser_config: ParserConfig, #[cfg(all(feature = "server", feature = "runtime"))] @@ -270,23 +270,23 @@ struct State { preserve_header_order: bool, title_case_headers: bool, h09_responses: bool, - /// If set, called with each 1xx informational response received for - /// the current request. MUST be unset after a non-1xx response is - /// received. + + + #[cfg(feature = "ffi")] on_informational: Option, #[cfg(feature = "ffi")] raw_headers: bool, - /// Set to true when the Dispatcher should poll read operations - /// again. See the `maybe_notify` method for more. + + notify_read: bool, - /// State of allowed reads + reading: Reading, - /// State of allowed writes + writing: Writing, - /// An expected pending HTTP upgrade. + upgrade: Option, - /// Either HTTP/1.0 or 1.1 connection + version: Version, } #[derive(Debug)] diff --git a/hyper/src/proto/h1/decode.rs b/hyper/src/proto/h1/decode.rs index 1e3a38e..2fde365 100644 --- a/hyper/src/proto/h1/decode.rs +++ b/hyper/src/proto/h1/decode.rs @@ -13,10 +13,10 @@ use super::DecodedLength; use self::Kind::{Chunked, Eof, Length}; -/// Decoders to handle different Transfer-Encodings. -/// -/// If a message body does not include a Transfer-Encoding, it *should* -/// include a Content-Length header. + + + + #[derive(Clone, PartialEq)] pub(crate) struct Decoder { kind: Kind, @@ -24,26 +24,26 @@ pub(crate) struct Decoder { #[derive(Debug, Clone, Copy, PartialEq)] enum Kind { - /// A Reader used when a Content-Length header is passed with a positive integer. + Length(u64), - /// A Reader used when Transfer-Encoding is `chunked`. + Chunked(ChunkedState, u64), - /// A Reader used for responses that don't indicate a length or chunked. - /// - /// The bool tracks when EOF is seen on the transport. - /// - /// Note: This should only used for `Response`s. It is illegal for a - /// `Request` to be made with both `Content-Length` and - /// `Transfer-Encoding: chunked` missing, as explained from the spec: - /// - /// > If a Transfer-Encoding header field is present in a response and - /// > the chunked transfer coding is not the final encoding, the - /// > message body length is determined by reading the connection until - /// > it is closed by the server. If a Transfer-Encoding header field - /// > is present in a request and the chunked transfer coding is not - /// > the final encoding, the message body length cannot be determined - /// > reliably; the server MUST respond with the 400 (Bad Request) - /// > status code and then close the connection. + + + + + + + + + + + + + + + + Eof(bool), } diff --git a/hyper/src/proto/h1/dispatch.rs b/hyper/src/proto/h1/dispatch.rs index 5ef9d1f..cea8c33 100644 --- a/hyper/src/proto/h1/dispatch.rs +++ b/hyper/src/proto/h1/dispatch.rs @@ -64,11 +64,11 @@ where pub(crate) fn into_inner(self) -> (I, Bytes, D) { loop {} } - /// Run this dispatcher until HTTP says this connection is done, - /// but don't call `AsyncWrite::shutdown` on the underlying IO. - /// - /// This is useful for old-style HTTP upgrades, but ignores - /// newer-style upgrade API. + + + + + pub(crate) fn poll_without_shutdown( &mut self, cx: &mut task::Context<'_>, @@ -133,8 +133,8 @@ where loop {} } } -/// A drop guard to allow a mutable borrow of an Option while being able to -/// set whether the `Option` should be cleared on drop. + + struct OptGuard<'a, T>(Pin<&'a mut Option>, bool); impl<'a, T> OptGuard<'a, T> { fn new(pin: Pin<&'a mut Option>) -> Self { diff --git a/hyper/src/proto/h1/encode.rs b/hyper/src/proto/h1/encode.rs index bc00455..378fcd8 100644 --- a/hyper/src/proto/h1/encode.rs +++ b/hyper/src/proto/h1/encode.rs @@ -5,7 +5,7 @@ use bytes::Buf; use super::io::WriteBuf; type StaticBuf = &'static [u8]; -/// Encoders to handle different Transfer-Encodings. + #[derive(Debug, Clone, PartialEq)] pub(crate) struct Encoder { kind: Kind, @@ -19,16 +19,16 @@ pub(crate) struct EncodedBuf { pub(crate) struct NotEof(u64); #[derive(Debug, PartialEq, Clone)] enum Kind { - /// An Encoder for when Transfer-Encoding includes `chunked`. + Chunked, - /// An Encoder for when Content-Length is set. - /// - /// Enforces that the body is not longer than the Content-Length header. + + + Length(u64), - /// An Encoder for when neither Content-Length nor Chunked encoding is set. - /// - /// This is mostly only used with HTTP/1.0 with a length. This kind requires - /// the connection to be closed when the body is finished. + + + + #[cfg(feature = "server")] CloseDelimited, } @@ -85,11 +85,11 @@ impl Encoder { { loop {} } - /// Encodes the full body, without verifying the remaining length matches. - /// - /// This is used in conjunction with HttpBody::__hyper_full_data(), which - /// means we can trust that the buf has the correct size (the buf itself - /// was checked to make the headers). + + + + + pub(super) fn danger_full_buf(self, msg: B, dst: &mut WriteBuf>) where B: Buf, diff --git a/hyper/src/proto/h1/io.rs b/hyper/src/proto/h1/io.rs index fe18508..2dd0af7 100644 --- a/hyper/src/proto/h1/io.rs +++ b/hyper/src/proto/h1/io.rs @@ -15,18 +15,18 @@ use tokio::time::Instant; use super::{Http1Transaction, ParseContext, ParsedMessage}; use crate::common::buf::BufList; use crate::common::{task, Poll}; -/// The initial buffer size allocated before trying to read from IO. + pub(crate) const INIT_BUFFER_SIZE: usize = 8192; -/// The minimum value that can be set to max buffer size. + pub(crate) const MINIMUM_MAX_BUFFER_SIZE: usize = INIT_BUFFER_SIZE; -/// The default maximum read buffer size. If the buffer gets this big and -/// a message is still not complete, a `TooLarge` error is triggered. + + pub(crate) const DEFAULT_MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100; -/// The maximum number of distinct `Buf`s to hold in a list before requiring -/// a flush. Only affects when the buffer strategy is to queue buffers. -/// -/// Note that a flush can happen before reaching the maximum. This simply -/// forces a flush if the queue gets this big. + + + + + const MAX_BUF_LIST_BUFFERS: usize = 16; pub(crate) struct Buffered { flush_pipeline: bool, @@ -77,16 +77,16 @@ where pub(super) fn read_buf_mut(&mut self) -> &mut BytesMut { loop {} } - /// Return the "allocated" available space, not the potential space - /// that could be allocated in the future. + + fn read_buf_remaining_mut(&self) -> usize { loop {} } - /// Return whether we can append to the headers buffer. - /// - /// Reasons we can't: - /// - The write buf is in queue mode, and some of the past body is still - /// needing to be flushed. + + + + + pub(crate) fn can_headers_buf(&self) -> bool { loop {} } @@ -136,10 +136,10 @@ where ) -> Poll> { loop {} } - /// Specialized version of `flush` when strategy is Flatten. - /// - /// Since all buffered bytes are flattened into the single headers buffer, - /// that skips some bookkeeping around using multiple buffers. + + + + fn poll_flush_flattened( &mut self, cx: &mut task::Context<'_>, @@ -217,9 +217,9 @@ impl> Cursor { } } impl Cursor> { - /// If we've advanced the position a bit in this cursor, and wish to - /// extend the underlying vector, we may wish to unshift the "read" bytes - /// off, and move everything else over. + + + fn maybe_unshift(&mut self, additional: usize) { loop {} } @@ -247,10 +247,10 @@ impl> Buf for Cursor { } } pub(super) struct WriteBuf { - /// Re-usable buffer that holds message headers + headers: Cursor>, max_buf_size: usize, - /// Deque of user buffers if strategy is Queue + queue: BufList, strategy: WriteStrategy, } diff --git a/hyper/src/proto/h1/mod.rs b/hyper/src/proto/h1/mod.rs index 086defc..48fcb32 100644 --- a/hyper/src/proto/h1/mod.rs +++ b/hyper/src/proto/h1/mod.rs @@ -48,7 +48,7 @@ pub(crate) trait Http1Transaction { } fn update_date() {} } -/// Result newtype for Http1Transaction::parse. + pub(crate) type ParseResult = Result>, crate::error::Parse>; #[derive(Debug)] pub(crate) struct ParsedMessage { @@ -77,7 +77,7 @@ pub(crate) struct ParseContext<'a> { #[cfg(feature = "ffi")] raw_headers: bool, } -/// Passed to Http1Transaction::encode + pub(crate) struct Encode<'a, T> { head: &'a mut MessageHead, body: Option, @@ -86,7 +86,7 @@ pub(crate) struct Encode<'a, T> { req_method: &'a mut Option, title_case_headers: bool, } -/// Extra flags that a request "wants", like expect-continue or upgrades. + #[derive(Clone, Copy, Debug)] struct Wants(u8); impl Wants { diff --git a/hyper/src/proto/h1/role.rs b/hyper/src/proto/h1/role.rs index 556d7bc..bb0ba9e 100644 --- a/hyper/src/proto/h1/role.rs +++ b/hyper/src/proto/h1/role.rs @@ -179,9 +179,9 @@ impl Http1Transaction for Client { } #[cfg(feature = "client")] impl Client { - /// Returns Some(length, wants_upgrade) if successful. - /// - /// Returns None if this message head should be skipped (like a 100 status). + + + fn decoder( inc: &MessageHead, method: &mut Option, diff --git a/hyper/src/proto/h2/mod.rs b/hyper/src/proto/h2/mod.rs index 681aec9..d647c95 100644 --- a/hyper/src/proto/h2/mod.rs +++ b/hyper/src/proto/h2/mod.rs @@ -19,7 +19,7 @@ cfg_client! { cfg_server! { pub (crate) mod server; pub (crate) use self::server::Server; } -/// Default initial stream window size defined in HTTP2 spec. + pub(crate) const SPEC_WINDOW_SIZE: u32 = 65_535; fn strip_connection_headers(headers: &mut HeaderMap, is_request: bool) { loop {} diff --git a/hyper/src/proto/h2/ping.rs b/hyper/src/proto/h2/ping.rs index 38b2d16..42f06ac 100644 --- a/hyper/src/proto/h2/ping.rs +++ b/hyper/src/proto/h2/ping.rs @@ -1,23 +1,23 @@ -/// HTTP2 Ping usage -/// -/// hyper uses HTTP2 pings for two purposes: -/// -/// 1. Adaptive flow control using BDP -/// 2. Connection keep-alive -/// -/// Both cases are optional. -/// -/// # BDP Algorithm -/// -/// 1. When receiving a DATA frame, if a BDP ping isn't outstanding: -/// 1a. Record current time. -/// 1b. Send a BDP ping. -/// 2. Increment the number of received bytes. -/// 3. When the BDP ping ack is received: -/// 3a. Record duration from sent time. -/// 3b. Merge RTT with a running average. -/// 3c. Calculate bdp as bytes/rtt. -/// 3d. If bdp is over 2/3 max, set new max to bdp and update windows. + + + + + + + + + + + + + + + + + + + + #[cfg(feature = "runtime")] use std::fmt; #[cfg(feature = "runtime")] @@ -43,14 +43,14 @@ pub(super) fn channel(ping_pong: PingPong, config: Config) -> (Recorder, Ponger) #[derive(Clone)] pub(super) struct Config { pub(super) bdp_initial_window: Option, - /// If no frames are received in this amount of time, a PING frame is sent. + #[cfg(feature = "runtime")] pub(super) keep_alive_interval: Option, - /// After sending a keepalive PING, the connection will be closed if - /// a pong is not received in this amount of time. + + #[cfg(feature = "runtime")] pub(super) keep_alive_timeout: Duration, - /// If true, sends pings even when there are no active streams. + #[cfg(feature = "runtime")] pub(super) keep_alive_while_idle: bool, } @@ -67,41 +67,41 @@ pub(super) struct Ponger { struct Shared { ping_pong: PingPong, ping_sent_at: Option, - /// If `Some`, bdp is enabled, and this tracks how many bytes have been - /// read during the current sample. + + bytes: Option, - /// We delay a variable amount of time between BDP pings. This allows us - /// to send less pings as the bandwidth stabilizes. + + next_bdp_at: Option, - /// If `Some`, keep-alive is enabled, and the Instant is how long ago - /// the connection read the last frame. + + #[cfg(feature = "runtime")] last_read_at: Option, #[cfg(feature = "runtime")] is_keep_alive_timed_out: bool, } struct Bdp { - /// Current BDP in bytes + bdp: u32, - /// Largest bandwidth we've seen so far. + max_bandwidth: f64, - /// Round trip time in seconds + rtt: f64, - /// Delay the next ping by this amount. - /// - /// This will change depending on how stable the current bandwidth is. + + + ping_delay: Duration, - /// The count of ping round trips where BDP has stayed the same. + stable_count: u32, } #[cfg(feature = "runtime")] struct KeepAlive { - /// If no frames are received in this amount of time, a PING frame is sent. + interval: Duration, - /// After sending a keepalive PING, the connection will be closed if - /// a pong is not received in this amount of time. + + timeout: Duration, - /// If true, sends pings even when there are no active streams. + while_idle: bool, state: KeepAliveState, timer: Pin>, @@ -132,8 +132,8 @@ impl Recorder { pub(crate) fn record_non_data(&self) { loop {} } - /// If the incoming stream is already closed, convert self into - /// a disabled reporter. + + #[cfg(feature = "client")] pub(super) fn for_stream(self, stream: &h2::RecvStream) -> Self { loop {} @@ -167,7 +167,7 @@ impl Shared { loop {} } } -/// Any higher than this likely will be hitting the TCP flow control. + const BDP_LIMIT: usize = 1024 * 1024 * 16; impl Bdp { fn calculate(&mut self, bytes: usize, rtt: Duration) -> Option { diff --git a/hyper/src/proto/mod.rs b/hyper/src/proto/mod.rs index c5fb9c5..e27688a 100644 --- a/hyper/src/proto/mod.rs +++ b/hyper/src/proto/mod.rs @@ -6,40 +6,40 @@ cfg_feature! { } #[cfg(feature = "http2")] pub(crate) mod h2; -/// An Incoming Message head. Includes request/status line, and headers. + #[derive(Debug, Default)] pub(crate) struct MessageHead { - /// HTTP version of the message. + pub(crate) version: http::Version, - /// Subject (request line or status line) of Incoming message. + pub(crate) subject: S, - /// Headers of the Incoming message. + pub(crate) headers: http::HeaderMap, - /// Extensions. + extensions: http::Extensions, } -/// An incoming request message. + #[cfg(feature = "http1")] pub(crate) type RequestHead = MessageHead; #[derive(Debug, Default, PartialEq)] #[cfg(feature = "http1")] pub(crate) struct RequestLine(pub(crate) http::Method, pub(crate) http::Uri); -/// An incoming response message. + #[cfg(all(feature = "http1", feature = "client"))] pub(crate) type ResponseHead = MessageHead; #[derive(Debug)] #[cfg(feature = "http1")] pub(crate) enum BodyLength { - /// Content-Length + Known(u64), - /// Transfer-Encoding: chunked (if h1) + Unknown, } -/// Status of when a Disaptcher future completes. + pub(crate) enum Dispatched { - /// Dispatcher completely shutdown connection. + Shutdown, - /// Dispatcher has pending upgrade, and so did not shutdown. + #[cfg(feature = "http1")] Upgrade(crate::upgrade::Pending), } diff --git a/hyper/src/rt.rs b/hyper/src/rt.rs index 2614b59..60c47cd 100644 --- a/hyper/src/rt.rs +++ b/hyper/src/rt.rs @@ -5,8 +5,8 @@ //! If the `runtime` feature is disabled, the types in this module can be used //! to plug in other runtimes. -/// An executor of futures. + pub trait Executor { - /// Place the future into the executor to be run. + fn execute(&self, fut: Fut); } diff --git a/hyper/src/server/accept.rs b/hyper/src/server/accept.rs index 6dd3e68..2d7b708 100644 --- a/hyper/src/server/accept.rs +++ b/hyper/src/server/accept.rs @@ -13,24 +13,24 @@ use crate::common::{ task::{self, Poll}, Pin, }; -/// Asynchronously accept incoming connections. + pub trait Accept { - /// The connection type that can be accepted. + type Conn; - /// The error type that can occur when accepting a connection. + type Error; - /// Poll to accept the next connection. + fn poll_accept( self: Pin<&mut Self>, cx: &mut task::Context<'_>, ) -> Poll>>; } -/// Adapt a `Stream` of incoming connections into an `Accept`. -/// -/// # Optional -/// -/// This function requires enabling the `stream` feature in your -/// `Cargo.toml`. + + + + + + #[cfg(feature = "stream")] pub fn from_stream(stream: S) -> impl Accept where diff --git a/hyper/src/server/conn.rs b/hyper/src/server/conn.rs index 407ee17..90f5207 100644 --- a/hyper/src/server/conn.rs +++ b/hyper/src/server/conn.rs @@ -65,29 +65,29 @@ cfg_feature! { } #[cfg(feature = "tcp")] pub use super::tcp::{AddrIncoming, AddrStream}; -/// A lower-level configuration of the HTTP protocol. -/// -/// This structure is used to configure options for an HTTP server connection. -/// -/// If you don't have need to manage connections yourself, consider using the -/// higher-level [Server](super) API. + + + + + + #[derive(Clone, Debug)] #[cfg(any(feature = "http1", feature = "http2"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub(crate) struct Http { pub(crate) exec: E, } -/// The internal mode of HTTP protocol which indicates the behavior when a parse error occurs. + #[cfg(any(feature = "http1", feature = "http2"))] #[derive(Clone, Debug, PartialEq)] enum ConnectionMode { - /// Always use HTTP/1 and do not upgrade when a parse error occurs. + #[cfg(feature = "http1")] H1Only, - /// Always use HTTP/2. + #[cfg(feature = "http2")] H2Only, - /// Use HTTP/1 and try to upgrade to h2 when a parse error occurs. + #[cfg(all(feature = "http1", feature = "http2"))] Fallback, } diff --git a/hyper/src/server/server.rs b/hyper/src/server/server.rs index 59160ca..33c4598 100644 --- a/hyper/src/server/server.rs +++ b/hyper/src/server/server.rs @@ -29,7 +29,7 @@ pin_project! { protocol : Http_ < E >, } } -/// A builder for a [`Server`](Server). + #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Builder { @@ -38,7 +38,7 @@ pub struct Builder { } #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Server { - /// Starts a [`Builder`](Builder) with the provided incoming stream. + pub fn builder(incoming: I) -> Builder { loop {} } @@ -49,12 +49,12 @@ impl Server { doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))) )] impl Server { - /// Binds to the provided address, and returns a [`Builder`](Builder). - /// - /// # Panics - /// - /// This method will panic if binding to the address fails. For a method - /// to bind to an address and return a `Result`, see `Server::try_bind`. + + + + + + pub fn bind() -> Builder { loop {} } @@ -71,42 +71,42 @@ where B::Error: Into>, E: ConnStreamExec<>::Future, B>, { - /// Prepares a server to handle graceful shutdown when the provided future - /// completes. - /// - /// # Example - /// - /// ``` - /// # fn main() {} - /// # #[cfg(feature = "tcp")] - /// # async fn run() { - /// # use hyper::{Body, Response, Server, Error}; - /// # use hyper::service::{make_service_fn, service_fn}; - /// # let make_service = make_service_fn(|_| async { - /// # Ok::<_, Error>(service_fn(|_req| async { - /// # Ok::<_, Error>(Response::new(Body::from("Hello World"))) - /// # })) - /// # }); - /// // Make a server from the previous examples... - /// let server = Server::bind(&([127, 0, 0, 1], 3000).into()) - /// .serve(make_service); - /// - /// // Prepare some signal for when the server should start shutting down... - /// let (tx, rx) = tokio::sync::oneshot::channel::<()>(); - /// let graceful = server - /// .with_graceful_shutdown(async { - /// rx.await.ok(); - /// }); - /// - /// // Await the `server` receiving the signal... - /// if let Err(e) = graceful.await { - /// eprintln!("server error: {}", e); - /// } - /// - /// // And later, trigger the signal by calling `tx.send(())`. - /// let _ = tx.send(()); - /// # } - /// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + fn poll_next_( self: Pin<&mut Self>, @@ -148,7 +148,7 @@ impl Builder { loop {} } - /// + pub fn serve(self, _: S) -> Server where I: Accept, diff --git a/hyper/src/server/tcp.rs b/hyper/src/server/tcp.rs index 2612e32..3f66ac8 100644 --- a/hyper/src/server/tcp.rs +++ b/hyper/src/server/tcp.rs @@ -52,7 +52,7 @@ impl TcpKeepaliveConfig { loop {} } } -/// A stream of connections from binding to an address. + #[must_use = "streams do nothing unless polled"] pub struct AddrIncoming { addr: SocketAddr, @@ -63,15 +63,15 @@ pub struct AddrIncoming { timeout: Option>>, } impl AddrIncoming { - /// Creates a new `AddrIncoming` binding to provided socket address. + pub fn bind(addr: &SocketAddr) -> crate::Result { loop {} } - /// Get the local address bound to this listener. + pub fn local_addr(&self) -> SocketAddr { loop {} } - /// Set the value of `TCP_NODELAY` option for accepted connections. + pub fn set_nodelay(&mut self, enabled: bool) -> &mut Self { loop {} } diff --git a/hyper/src/service/http.rs b/hyper/src/service/http.rs index 6383e19..9b4d0e4 100644 --- a/hyper/src/service/http.rs +++ b/hyper/src/service/http.rs @@ -2,17 +2,17 @@ use std::error::Error as StdError; use crate::body::HttpBody; use crate::common::{task, Future, Poll}; use crate::{Request, Response}; -/// An asynchronous function from `Request` to `Response`. + pub trait HttpService: sealed::Sealed { - /// The `HttpBody` body of the `http::Response`. + type ResBody: HttpBody; - /// 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>; - /// The `Future` returned by this `Service`. + type Future: Future, Self::Error>>; #[doc(hidden)] fn poll_ready( diff --git a/hyper/src/service/make.rs b/hyper/src/service/make.rs index 3e3c6c7..0ad3ead 100644 --- a/hyper/src/service/make.rs +++ b/hyper/src/service/make.rs @@ -82,42 +82,42 @@ where B1: HttpBody, B2: HttpBody, {} -/// Create a `MakeService` from a function. -/// -/// # Example -/// -/// ``` -/// # #[cfg(feature = "runtime")] -/// # async fn run() { -/// use std::convert::Infallible; -/// use hyper::{Body, Request, Response, Server}; -/// use hyper::server::conn::AddrStream; -/// use hyper::service::{make_service_fn, service_fn}; -/// -/// let addr = ([127, 0, 0, 1], 3000).into(); -/// -/// let make_svc = make_service_fn(|socket: &AddrStream| { -/// let remote_addr = socket.remote_addr(); -/// async move { -/// Ok::<_, Infallible>(service_fn(move |_: Request| async move { -/// Ok::<_, Infallible>( -/// Response::new(Body::from(format!("Hello, {}!", remote_addr))) -/// ) -/// })) -/// } -/// }); -/// -/// // Then bind and serve... -/// let server = Server::bind(&addr) -/// .serve(make_svc); -/// -/// // Finally, spawn `server` onto an Executor... -/// if let Err(e) = server.await { -/// eprintln!("server error: {}", e); -/// } -/// # } -/// # fn main() {} -/// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub fn make_service_fn(f: F) -> MakeServiceFn where F: FnMut(&Target) -> Ret, @@ -125,7 +125,7 @@ where { loop {} } -/// `MakeService` returned from [`make_service_fn`] + #[derive(Clone, Copy)] pub struct MakeServiceFn { f: F, diff --git a/hyper/src/service/util.rs b/hyper/src/service/util.rs index b94f465..82020a5 100644 --- a/hyper/src/service/util.rs +++ b/hyper/src/service/util.rs @@ -4,24 +4,24 @@ use std::marker::PhantomData; use crate::body::HttpBody; use crate::common::{task, Future, Poll}; use crate::{Request, Response}; -/// Create a `Service` from a function. -/// -/// # Example -/// -/// ``` -/// use hyper::{Body, Request, Response, Version}; -/// use hyper::service::service_fn; -/// -/// let service = service_fn(|req: Request| async move { -/// if req.version() == Version::HTTP_11 { -/// Ok(Response::new(Body::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: F) -> ServiceFn where F: FnMut(Request) -> S, @@ -29,7 +29,7 @@ where { loop {} } -/// Service returned by [`service_fn`] + pub struct ServiceFn { f: F, _req: PhantomData, diff --git a/hyper/src/upgrade.rs b/hyper/src/upgrade.rs index 000e8c3..c633341 100644 --- a/hyper/src/upgrade.rs +++ b/hyper/src/upgrade.rs @@ -49,50 +49,50 @@ use tokio::sync::oneshot; use crate::common::io::Rewind; use crate::common::{task, Future, Pin, Poll}; -/// An upgraded HTTP connection. -/// -/// This type holds a trait object internally of the original IO that -/// was used to speak HTTP before the upgrade. It can be used directly -/// as a `Read` or `Write` for convenience. -/// -/// Alternatively, if the exact type is known, this can be deconstructed -/// into its parts. + + + + + + + + pub(crate) struct Upgraded { io: Rewind>, } -/// A future for a possible HTTP upgrade. -/// -/// If no upgrade was available, or it doesn't succeed, yields an `Error`. + + + pub(crate) struct OnUpgrade { rx: Option>>, } -/// The deconstructed parts of an [`Upgraded`](Upgraded) type. -/// -/// Includes the original IO type, and a read buffer of bytes that the -/// HTTP state machine may have already read before completing an upgrade. + + + + #[derive(Debug)] pub(crate) struct Parts { - /// The original IO object used before the upgrade. + pub(crate) io: T, - /// A buffer of bytes that have been read but not processed as HTTP. - /// - /// For instance, if the `Connection` is used for an HTTP upgrade request, - /// it is possible the server sent back the first bytes of the new protocol - /// along with the response upgrade. - /// - /// You will want to check for any existing bytes if you plan to continue - /// communicating on the IO object. + + + + + + + + pub(crate) read_buf: Bytes, _inner: (), } -/// Gets a pending HTTP upgrade from this message. -/// -/// This can be called on the following types: -/// -/// - `http::Request` -/// - `http::Response` -/// - `&mut http::Request` -/// - `&mut http::Response` + + + + + + + + pub(crate) fn on(msg: T) -> OnUpgrade { loop {} } @@ -112,10 +112,10 @@ impl Upgraded { { loop {} } - /// Tries to downcast the internal trait object to the type passed. - /// - /// On success, returns the downcasted parts. On error, returns the - /// `Upgraded` back. + + + + pub(crate) fn downcast( self, ) -> Result, Self> { @@ -193,16 +193,16 @@ impl Pending { loop {} } #[cfg(feature = "http1")] - /// Don't fulfill the pending Upgrade, but instead signal that - /// upgrades are handled manually. + + pub(super) fn manual(self) { loop {} } } -/// Error cause returned when an upgrade was expected but canceled -/// for whatever reason. -/// -/// This likely means the actual `Conn` future wasn't polled and upgraded. + + + + #[derive(Debug)] struct UpgradeExpected; impl fmt::Display for UpgradeExpected { diff --git a/warp/src/error.rs b/warp/src/error.rs index 2bdde4e..542e35a 100644 --- a/warp/src/error.rs +++ b/warp/src/error.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; use std::error::Error as StdError; use std::fmt; type BoxError = Box; -/// Errors that can happen inside warp. + pub struct Error { inner: BoxError, } diff --git a/warp/src/filter/boxed.rs b/warp/src/filter/boxed.rs index 8f1a9bf..f0cf93a 100644 --- a/warp/src/filter/boxed.rs +++ b/warp/src/filter/boxed.rs @@ -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 { filter: Arc< dyn Filter< diff --git a/warp/src/filter/mod.rs b/warp/src/filter/mod.rs index 43c85db..36be1e2 100644 --- a/warp/src/filter/mod.rs +++ b/warp/src/filter/mod.rs @@ -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::()); - /// ``` + + + + + + + + + + + + + + + + + + + fn and(self, other: F) -> And 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::() - /// .or(warp::path::param::()); - /// ``` + + + + + + + + + + + + fn or(self, other: F) -> Or where Self: Filter + 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(self, fun: F) -> Map 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(self, fun: F) -> Then 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(self, fun: F) -> AndThen 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(self, fun: F) -> OrElse where Self: Filter + 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(self, fun: F) -> Recover where Self: Filter + 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`, 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(self) -> Unify where Self: Filter,)> + 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(self) -> UntupleOne where Self: Filter + 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(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::() - /// .boxed() - /// } - /// - /// fn named_and() -> warp::filters::BoxedFilter<(i32, String)> { - /// warp::path::param::() - /// .and(warp::header::("host")) - /// .boxed() - /// } - /// ``` + + + + + + + + + + + + + + + + + + + + + + + + fn boxed(self) -> BoxedFilter where Self: Sized + Send + Sync + 'static, diff --git a/warp/src/filter/service.rs b/warp/src/filter/service.rs index 76a7972..a9d6b58 100644 --- a/warp/src/filter/service.rs +++ b/warp/src/filter/service.rs @@ -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> { -/// 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(filter: F) -> FilteredService where F: Filter, diff --git a/warp/src/filter/wrap.rs b/warp/src/filter/wrap.rs index 416a43e..9dc42a6 100644 --- a/warp/src/filter/wrap.rs +++ b/warp/src/filter/wrap.rs @@ -19,19 +19,19 @@ where T: WrapSealed, 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(func: F) -> WrapFn where F: Fn(T) -> U, diff --git a/warp/src/filters/addr.rs b/warp/src/filters/addr.rs index 3d63070..2d8e142 100644 --- a/warp/src/filters/addr.rs +++ b/warp/src/filters/addr.rs @@ -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| { -/// println!("remote address = {:?}", addr); -/// }); -/// ``` + + + + + + + + + + + + + + + + pub fn remote() -> impl Filter,), Error = Infallible> + Copy { filter_fn_one(|route| futures_util::future::ok(route.remote_addr())) } diff --git a/warp/src/filters/any.rs b/warp/src/filters/any.rs index 136707e..9d098f6 100644 --- a/warp/src/filters/any.rs +++ b/warp/src/filters/any.rs @@ -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>| { -/// db.contains(¶m_id) -/// }); -/// ``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pub fn any() -> impl Filter + Copy { Any } diff --git a/warp/src/filters/body.rs b/warp/src/filters/body.rs index a84b12b..5850f18 100644 --- a/warp/src/filters/body.rs +++ b/warp/src/filters/body.rs @@ -31,20 +31,20 @@ pub(crate) fn body() -> impl Filter + 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 + 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>,), 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 + Copy { body() .and_then(|body: hyper::Body| { @@ -114,35 +114,35 @@ pub fn bytes() -> impl Filter + 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 + Copy { body() .and_then(|body: ::hyper::Body| { @@ -153,26 +153,26 @@ pub fn aggregate() -> impl Filter + 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| { -/// "Got a JSON body!" -/// }); -/// ``` + + + + + + + + + + + + + + + + + + + + pub fn json() -> impl Filter< Extract = (T,), Error = Rejection, @@ -187,30 +187,30 @@ pub fn json() -> 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| { -/// "Got a urlencoded body!" -/// }); -/// ``` + + + + + + + + + + + + + + + + + + + + + + + + pub fn form() -> 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, diff --git a/warp/src/filters/compression.rs b/warp/src/filters/compression.rs index 4bc9ef0..19dd159 100644 --- a/warp/src/filters/compression.rs +++ b/warp/src/filters/compression.rs @@ -29,58 +29,58 @@ impl From for HeaderValue { loop {} } } -/// Compression + #[derive(Clone, Copy, Debug)] pub struct Compression { 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 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 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 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 @@ -139,7 +139,7 @@ mod internal { loop {} } } - /// Compression Props + #[derive(Debug)] pub struct CompressionProps { pub(super) body: CompressableBody, diff --git a/warp/src/filters/cookie.rs b/warp/src/filters/cookie.rs index 53695e8..269d715 100644 --- a/warp/src/filters/cookie.rs +++ b/warp/src/filters/cookie.rs @@ -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(name: &'static str) -> impl Filter, 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( name: &'static str, ) -> impl Filter>, Error = Infallible> + Copy diff --git a/warp/src/filters/cors.rs b/warp/src/filters/cors.rs index dd3cbda..20ef095 100644 --- a/warp/src/filters/cors.rs +++ b/warp/src/filters/cors.rs @@ -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, } -/// A constructed via `warp::cors()`. + #[derive(Clone, Debug)] pub struct Builder { credentials: bool, @@ -56,26 +56,26 @@ pub struct Builder { origins: Option>, } 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(mut self, method: M) -> Self where http::Method: TryFrom, { 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(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(mut self, header: H) -> Self where HeaderName: TryFrom, { 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(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(mut self, header: H) -> Self where HeaderName: TryFrom, { 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(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(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, } diff --git a/warp/src/filters/ext.rs b/warp/src/filters/ext.rs index 985bbfb..9096a79 100644 --- a/warp/src/filters/ext.rs +++ b/warp/src/filters/ext.rs @@ -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( ) -> impl Filter + Copy { filter_fn_one(|route| { @@ -22,15 +22,15 @@ pub fn get( }) } -/// Get a previously set extension of the current route. -/// -/// If the extension doesn't exist, it yields `None`. + + + pub fn optional( ) -> impl Filter,), Error = Infallible> + Copy { filter_fn_one(|route| future::ok(route.extensions().get::().cloned())) } unit_error! { - /// An error used to reject if `get` cannot find the extension. + pub MissingExtension: "Missing request extension" } diff --git a/warp/src/filters/fs.rs b/warp/src/filters/fs.rs index 55575d2..27d3156 100644 --- a/warp/src/filters/fs.rs +++ b/warp/src/filters/fs.rs @@ -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, ) -> impl FilterClone, 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, ) -> impl FilterClone, 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 {} } diff --git a/warp/src/filters/header.rs b/warp/src/filters/header.rs index 0c535a3..5ac04c1 100644 --- a/warp/src/filters/header.rs +++ b/warp/src/filters/header.rs @@ -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::("content-length"); -/// -/// // Parse `host: 127.0.0.1:8080` as a `SocketAddr -/// let local_host = warp::header::("host"); -/// -/// // Parse `foo: bar` into a `String` -/// let foo = warp::header::("foo"); -/// ``` + + + + + + + + + + + + + + + + + + + pub fn header( name: &'static str, ) -> impl Filter, Error = Rejection> + Copy { @@ -61,18 +61,18 @@ pub(crate) fn header2( }) } -/// 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::("authorization"); -/// ``` + + + + + + + + + + + + pub fn optional( name: &'static str, ) -> impl Filter>, 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, 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, Error = Infallible> + Copy { filter_fn_one(|route| future::ok(route.headers().clone())) } diff --git a/warp/src/filters/host.rs b/warp/src/filters/host.rs index 9aae039..437ca2d 100644 --- a/warp/src/filters/host.rs +++ b/warp/src/filters/host.rs @@ -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 + Clone { let expected = Authority::from_str(expected).expect("invalid host/authority"); optional() @@ -30,31 +30,31 @@ pub fn exact(expected: &str) -> impl Filter + 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| { -/// 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>, Error = Rejection> + Copy { filter_fn_one(move |route| { // The authority can be sent by clients in various ways: diff --git a/warp/src/filters/log.rs b/warp/src/filters/log.rs index f7c51b1..745803e 100644 --- a/warp/src/filters/log.rs +++ b/warp/src/filters/log.rs @@ -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) + Copy> { let func = move |info: Info<'_>| { log::info!( @@ -36,38 +36,38 @@ pub fn log(name: &'static str) -> Log) + 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(func: F) -> Log where F: Fn(Info<'_>), { loop {} } -/// Decorates a [`Filter`](crate::Filter) to log requests and responses. + #[derive(Clone, Copy, Debug)] pub struct Log { 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 { 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 {} } diff --git a/warp/src/filters/method.rs b/warp/src/filters/method.rs index 80c00e2..c49d276 100644 --- a/warp/src/filters/method.rs +++ b/warp/src/filters/method.rs @@ -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 + 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 + 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 + 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 + 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 + 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 + 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 + 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, Error = Infallible> + Copy { filter_fn_one(|route| future::ok::<_, Infallible>(route.method().clone())) } diff --git a/warp/src/filters/multipart.rs b/warp/src/filters/multipart.rs index d58587c..56e388f 100644 --- a/warp/src/filters/multipart.rs +++ b/warp/src/filters/multipart.rs @@ -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>, } -/// A single "part" of a multipart/form-data body. -/// -/// Yielded from the `FormData` stream. + + + pub struct Part { name: String, filename: Option, content_type: Option, data: Option>, } -/// 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> { loop {} } - /// Convert this `Part` into a `Stream` of `Buf`s. + pub fn stream(self) -> impl Stream> { loop {} } diff --git a/warp/src/filters/path.rs b/warp/src/filters/path.rs index 545b21f..c29f2bb 100644 --- a/warp/src/filters/path.rs +++ b/warp/src/filters/path.rs @@ -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) -> Exact> where P: AsRef, { loop {} } -/// A `Filter` matching an exact path segment. -/// -/// Constructed from `path()` or `path!()`. + + + #[allow(missing_debug_implementations)] #[derive(Clone, Copy)] pub struct Exact

(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 + Copy { filter_fn(move |route| { if route.path().is_empty() { @@ -207,24 +207,24 @@ pub fn end() -> impl Filter + 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() -> impl Filter< Extract = One, Error = Rejection, @@ -237,23 +237,23 @@ pub fn param() -> 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, Error = Infallible> + Copy { filter_fn(move |route| { let path = path_and_query(route); @@ -263,13 +263,13 @@ pub fn tail() -> impl Filter, 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, Error = Infallible> + Copy { filter_fn(move |route| { let path = path_and_query(route); @@ -304,17 +304,17 @@ pub fn peek() -> impl Filter, 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 { 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, 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::()) -/// .and(warp::path::param::()) -/// .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)] diff --git a/warp/src/filters/query.rs b/warp/src/filters/query.rs index 7aee569..f46891f 100644 --- a/warp/src/filters/query.rs +++ b/warp/src/filters/query.rs @@ -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::>()) -/// .map(|map: HashMap| { -/// let mut response: Vec = 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, -/// bar: u8, -/// } -/// -/// let route = warp::any() -/// .and(warp::query::()) -/// .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( ) -> impl Filter, Error = Rejection> + Copy { filter_fn_one(|route| { @@ -78,7 +78,7 @@ pub fn query( }) } -/// Creates a `Filter` that returns the raw query string as type String. + pub fn raw() -> impl Filter, Error = Rejection> + Copy { filter_fn_one(|route| { let route = route diff --git a/warp/src/filters/reply.rs b/warp/src/filters/reply.rs index e202888..24f3b39 100644 --- a/warp/src/filters/reply.rs +++ b/warp/src/filters/reply.rs @@ -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(name: K, value: V) -> WithHeader where HeaderName: TryFrom, @@ -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(name: K, value: V) -> WithDefaultHeader where HeaderName: TryFrom, @@ -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, @@ -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, diff --git a/warp/src/filters/sse.rs b/warp/src/filters/sse.rs index 519412a..fd2ecee 100644 --- a/warp/src/filters/sse.rs +++ b/warp/src/filters/sse.rs @@ -63,7 +63,7 @@ enum DataType { Text(String), Json(String), } -/// Server-sent event + #[derive(Default, Debug)] pub struct Event { id: Option, @@ -73,33 +73,33 @@ pub struct Event { retry: Option, } impl Event { - /// Set Server-sent event data - /// data field(s) ("data:") + + pub fn data>(mut self, data: T) -> Event { loop {} } - /// Set Server-sent event data - /// data field(s) ("data:") + + pub fn json_data(mut self, data: T) -> Result { loop {} } - /// Set Server-sent event comment - /// Comment field (":") + + pub fn comment>(mut self, comment: T) -> Event { loop {} } - /// Set Server-sent event event - /// Event name field ("event:") + + pub fn event>(mut self, event: T) -> Event { loop {} } - /// Set Server-sent event retry - /// Retry timeout field ("retry:") + + pub fn retry(mut self, duration: Duration) -> Event { loop {} } - /// Set Server-sent event id - /// Identifier field ("id:") + + pub fn id>(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::(); -/// -/// // 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() -> impl Filter< Extract = One>, 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> { -/// 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(event_stream: S) -> impl Reply where S: TryStream + 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>) -> Self { loop {} } - /// Wrap an event stream with keep-alive functionality. - /// - /// See [`keep_alive`](keep_alive) for more. + + + pub fn stream( self, event_stream: S, @@ -305,51 +305,51 @@ struct SseKeepAlive { #[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 { -/// 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 { diff --git a/warp/src/filters/trace.rs b/warp/src/filters/trace.rs index 5843ed5..763b8de 100644 --- a/warp/src/filters/trace.rs +++ b/warp/src/filters/trace.rs @@ -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) -> 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(func: F) -> Trace 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) -> 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 { 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 { 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 {} } diff --git a/warp/src/filters/ws.rs b/warp/src/filters/ws.rs index 3b10983..eb2c496 100644 --- a/warp/src/filters/ws.rs +++ b/warp/src/filters/ws.rs @@ -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, Error = Rejection> + Copy { loop {} } -/// Extracted by the [`ws`](ws) filter, and used to finish an upgrade. + pub struct Ws { config: Option, key: SecWebsocketKey, on_upgrade: Option, } impl Ws { - /// Finish the upgrade, passing a function to handle the `WebSocket`. - /// - /// The passed function must return a `Future`. + + + pub fn on_upgrade(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, } @@ -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: S) -> Message { loop {} } - /// Construct a new Binary `Message`. + pub fn binary>>(v: V) -> Message { loop {} } - /// Construct a new Ping `Message`. + pub fn ping>>(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: 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, reason: impl Into>, ) -> 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 { loop {} } @@ -244,7 +244,7 @@ impl From for Vec { loop {} } } -/// Connection header did not include 'upgrade' + #[derive(Debug)] pub struct MissingConnectionUpgrade; impl fmt::Display for MissingConnectionUpgrade { diff --git a/warp/src/redirect.rs b/warp/src/redirect.rs index 4fd5423..377ea5d 100644 --- a/warp/src/redirect.rs +++ b/warp/src/redirect.rs @@ -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; diff --git a/warp/src/reject.rs b/warp/src/reject.rs index d75069d..e381fa5 100644 --- a/warp/src/reject.rs +++ b/warp/src/reject.rs @@ -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(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>(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::() { - /// println!("found it: {:?}", nope); - /// } - /// ``` + + + + + + + + + + + + + + + + + + + pub fn find(&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: 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 + From + Into; - /// 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; } diff --git a/warp/src/reply.rs b/warp/src/reply.rs index e91d8d4..215f9e3 100644 --- a/warp/src/reply.rs +++ b/warp/src/reply.rs @@ -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; -/// 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(val: &T) -> Json where T: Serialize, { loop {} } -/// A JSON formatted reply. + #[allow(missing_debug_implementations)] pub struct Json { inner: Result, ()>, @@ -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 with warp! -/// -/// -///

warp + HTML = ♥

-/// -/// -/// "#; -/// -/// let route = warp::any() -/// .map(move || { -/// warp::reply::html(body) -/// }); -/// ``` + + + + + + + + + + + + + + + + + + + + + + + pub fn html(body: T) -> Html where Body: From, @@ -146,7 +146,7 @@ where { loop {} } -/// An HTML reply. + #[allow(missing_debug_implementations)] pub struct Html { 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>` -/// - `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 Reply for Box { @@ -205,25 +205,25 @@ impl Reply for Box { 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(reply: T, status: StatusCode) -> WithStatus { loop {} } -/// Wrap an `impl Reply` to change its `StatusCode`. -/// -/// Returned by `warp::reply::with_status`. + + + #[derive(Debug)] pub struct WithStatus { reply: T, @@ -234,19 +234,19 @@ impl Reply for WithStatus { 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(reply: T, name: K, value: V) -> WithHeader where HeaderName: TryFrom, @@ -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 { header: Option<(HeaderName, HeaderValue)>, diff --git a/warp/src/server.rs b/warp/src/server.rs index 89e91f5..1be1777 100644 --- a/warp/src/server.rs +++ b/warp/src/server.rs @@ -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(filter: F) -> Server 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 { 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 { server: Server, @@ -92,14 +92,14 @@ where ::Ok: Reply, ::Error: IsReject, { - /// Run this `Server` forever on the current thread. + pub async fn run(self, addr: impl Into) { 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(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 + '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) { 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, @@ -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, @@ -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(self, incoming: I) -> impl Future 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( 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 { loop {} @@ -283,69 +283,69 @@ where ::Ok: Reply, ::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) -> Self { loop {} } - /// Specify the file path to read the certificate. - /// - /// *This function requires the `"tls"` feature.* + + + pub fn cert_path(self, path: impl AsRef) -> 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) -> 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) -> 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) { 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) { 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, impl Future + '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 + 'static, diff --git a/warp/src/test.rs b/warp/src/test.rs index e74195c..c8ea25b 100644 --- a/warp/src/test.rs +++ b/warp/src/test.rs @@ -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, 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, rx: mpsc::UnboundedReceiver>, } -/// An error from Websocket filter tests. + #[derive(Debug)] pub struct WsError { cause: Box, } 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(mut self, key: K, value: V) -> Self where HeaderName: TryFrom, @@ -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(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::(); - /// - /// let ex = warp::test::request() - /// .path("/41") - /// .filter(¶m) - /// .await - /// .unwrap(); - /// - /// assert_eq!(ex, 41); - /// - /// assert!( - /// warp::test::request() - /// .path("/foo") - /// .filter(¶m) - /// .await - /// .is_err() - /// ); - ///}; - /// ``` + + + + + + + + + + + + + + + + + + + + + + + + + pub async fn filter( 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(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(self, f: &F) -> Response 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(self, key: K, value: V) -> Self where HeaderName: TryFrom, @@ -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(self, f: F) -> Result 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) { 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 { loop {} } - /// Assert the server has closed the connection. + pub async fn recv_closed(&mut self) -> Result<(), WsError> { loop {} } diff --git a/warp/src/tls.rs b/warp/src/tls.rs index 350a2d7..154c4b5 100644 --- a/warp/src/tls.rs +++ b/warp/src/tls.rs @@ -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), - /// Allow any authenticated client. + Required(Box), } -/// Builder to set the configuration for the Tls server. + pub(crate) struct TlsConfigBuilder { cert: Box, key: Box, @@ -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) -> 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) -> 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) -> 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) -> 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 {} }