pub struct BoundedHttpClient { /* private fields */ }Expand description
Wraps any HttpClient so the port’s bounds hold on every runtime:
the deadline is enforced through the Clock port (the
only timer core is allowed to use), and the response is refused — by
declared length before anything else, then by actual size — when it
exceeds the HttpPolicy cap.
This is defence in depth, not the only defence: the native adapter
also enforces the cap while streaming (before the oversized body is
ever buffered) and the Workers adapter checks the declared length and
then reads the body as a stream under the same cap, aborting at the
chunk that crosses it. Runtimes wire every ports.http through
this wrapper.
Streaming (send_streaming) is bounded the same way, with the body’s
own seam: the head under the HttpPolicy deadline, the body under
the StreamPolicy’s idle gap, whole-body ceiling and byte cap — all
measured through the same clock, all dropping the inner body (and with
it the upstream exchange) on the way out. Whichever time bound ends
the body names itself in the HttpError::DeadlineExceeded it
raises: the idle gap when a quiet gap was what expired, the whole-body
ceiling when that did.
Implementations§
Trait Implementations§
Source§impl HttpClient for BoundedHttpClient
impl HttpClient for BoundedHttpClient
Source§fn send<'life0, 'async_trait>(
&'life0 self,
request: Request<Bytes>,
) -> Pin<Box<dyn Future<Output = Result<Response<Bytes>, HttpError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn send<'life0, 'async_trait>(
&'life0 self,
request: Request<Bytes>,
) -> Pin<Box<dyn Future<Output = Result<Response<Bytes>, HttpError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
request and returns the fully-buffered response under the
bounds this port carries: the body is at most
MAX_RESPONSE_BYTES unless an HttpPolicy tightens it, the
exchange is bounded by that policy’s deadline
(enforced through BoundedHttpClient on runtimes that wrap),
the destination is vetted where real sockets are opened, and a
runtime that keeps a concurrency budget holds one for the send. Read moreSource§fn send_streaming<'life0, 'async_trait>(
&'life0 self,
request: Request<Bytes>,
) -> Pin<Box<dyn Future<Output = Result<Response<ByteStream>, HttpError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn send_streaming<'life0, 'async_trait>(
&'life0 self,
request: Request<Bytes>,
) -> Pin<Box<dyn Future<Output = Result<Response<ByteStream>, HttpError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
request and returns the response with its body as a
stream (issue #859): the status and headers are known when the
future resolves — the head is bounded by HttpPolicy::timeout,
the same deadline send answers under — and the bytes arrive chunk
by chunk afterwards, under the StreamPolicy the request carries. Read more