Skip to main content

HttpClient

Trait HttpClient 

Source
pub trait HttpClient: Send + Sync {
    // Required method
    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;

    // Provided method
    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 { ... }
}

Required Methods§

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,

Sends 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.

An implementation MAY honour a StatusOnly request extension by answering with no body and no body-describing headers; an implementation that does not read the extension answers it like any other request. The Workers port honours it today.

Provided Methods§

Source

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,

Sends 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.

The body’s bounds — the idle gap, the whole-body ceiling, the StreamPolicy::max_bytes cap and the declared-length refusal — are BoundedHttpClient’s, which every runtime wires around its transport; an implementation MAY enforce some of them itself (the native port applies the byte cap while streaming), and one that does not streams unbounded. Callers reach a transport only through the runtime’s wrapper, so the bounds hold on every supported path.

§Cancellation

Dropping the returned body MUST abort the upstream exchange. This is what makes cancellation affordable on this port: a route whose client disconnects mid-completion drops the stream, the transport drops the request, and the upstream stops billing for a body nobody is reading. The BoundedHttpClient wrapper preserves the property on expiry and over-cap paths by dropping the inner body it wraps.

The default implementation buffers: it calls Self::send and yields the whole body as one chunk. That is correct — every bound still holds — but it is not incremental, so a transport that can stream natively SHOULD override this; a caller cannot tell the difference except by timing.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§