///|
/// A readable response body. None signals end of stream.
pub(open) trait BodyStream {
/// Reads the next chunk, or None at end of stream.
async fn read_some(Self) -> Bytes? raise HttpError
/// Releases the stream's resources.
fn close(Self) -> Unit
}
///|
/// Sends requests without interpreting HTTP status codes as errors.
pub(open) trait Transport {
/// Sends a request and reads its entire response body.
async fn send(Self, Request) -> Response raise HttpError
/// Sends a request and returns the response head and a readable body.
async fn send_stream(Self, Request) -> (ResponseHead, &BodyStream) raise HttpError
}
///|
/// Transport failures, separate from ordinary HTTP response statuses.
pub(all) suberror HttpError {
Connect(String)
Timeout(Int)
Protocol(String)
} derive(Debug)
///|
/// Debug representation of a transport failure.
pub extend HttpError with @debug.Debug::{to_repr}
///|
/// An async request wrapper receiving the next operation in the chain.
pub type Middleware = async (
Request,
async (Request) -> Response raise HttpError,
) -> Response raise HttpError
///|
/// Sends through middleware in array order, with the first element outermost.
pub async fn send_with(
transport : &Transport,
middleware : Array[Middleware],
request : Request,
) -> Response raise HttpError {
let mut next : async (Request) -> Response raise HttpError = request => {
transport.send(request)
}
for i = middleware.length() - 1; i >= 0; i = i - 1 {
let inner = next
let wrapper = middleware[i]
next = request => wrapper(request, inner)
}
next(request)
}