rig_http/http_client/middleware.rs
1//! Transport-boundary middleware for [`DynHttpClient`](super::DynHttpClient).
2//! Attach hooks with [`with_middleware`](super::DynHttpClient::with_middleware).
3//!
4//! ```
5//! use rig_http::http_client::middleware::HttpMiddleware;
6//!
7//! struct PassThrough;
8//! impl HttpMiddleware for PassThrough {}
9//! ```
10
11use bytes::Bytes;
12use http::{HeaderMap, Method, StatusCode, Uri};
13
14use super::Result;
15use crate::wasm_compat::{WasmBoxedFuture, WasmCompatSend, WasmCompatSync};
16
17/// Transport-boundary hooks applied by
18/// [`DynHttpClient`](super::DynHttpClient) around every request.
19///
20/// Methods default to no-ops. All header hooks run in attachment order, then
21/// all body hooks run in that order with the final headers and preceding body
22/// replacements. Response hooks run in attachment order after the transport
23/// returns a response, before streaming-body consumption. A transport that
24/// returns an error for an error status, as `rig-reqwest` does, skips them
25/// for that reply. Multipart requests skip body hooks.
26///
27/// Any hook error fails the request; request-side errors abort before sending.
28/// Response hooks cannot modify responses. Hooks run on the request future and
29/// must not block.
30pub trait HttpMiddleware: WasmCompatSend + WasmCompatSync {
31 /// Mutate the outgoing request headers in place.
32 ///
33 /// Runs before [`before_request_body`](Self::before_request_body). An
34 /// error aborts the request before it is sent.
35 fn before_request_headers<'a>(
36 &'a self,
37 _method: &'a Method,
38 _uri: &'a Uri,
39 _headers: &'a mut HeaderMap,
40 ) -> WasmBoxedFuture<'a, Result<()>> {
41 Box::pin(async { Ok(()) })
42 }
43
44 /// Observe the serialized request body, returning the body to send.
45 ///
46 /// Return `body` unchanged to pass through, or a replacement to rewrite
47 /// the payload. `headers` reflects every middleware's header mutations.
48 /// Not invoked for multipart requests. An error aborts the request before
49 /// it is sent.
50 fn before_request_body<'a>(
51 &'a self,
52 _method: &'a Method,
53 _uri: &'a Uri,
54 _headers: &'a HeaderMap,
55 body: Bytes,
56 ) -> WasmBoxedFuture<'a, Result<Bytes>> {
57 Box::pin(async move { Ok(body) })
58 }
59
60 /// Observe the response status and headers as soon as they arrive.
61 /// Not invoked when the transport fails the request, which includes a
62 /// non-success status on a transport that reports one as an error.
63 ///
64 /// For streaming responses this runs before any of the body stream is
65 /// consumed. Observe-only: the response cannot be modified, but returning
66 /// an error fails the request with that error.
67 fn after_response<'a>(
68 &'a self,
69 _method: &'a Method,
70 _uri: &'a Uri,
71 _status: StatusCode,
72 _headers: &'a HeaderMap,
73 ) -> WasmBoxedFuture<'a, Result<()>> {
74 Box::pin(async { Ok(()) })
75 }
76}