pub struct ClientIpContext {
pub trusted_proxy: Option<TrustedProxyConfig>,
pub peer: Option<SocketAddr>,
pub extensions: Extensions,
}Expand description
The trusted-proxy configuration (if an Extension<TrustedProxyConfig>
was applied to the router), the verified socket peer (if the router
is served via into_make_service_with_connect_info), and a clone of
the request’s full http::Extensions map, bundled into a single axum
extractor so every generated dispatch fn threads one new parameter
instead of several (#415).
The extensions field (added for the AuthProvider::authenticate
extensions plumbing, request_context — see cratestack_core:: RequestContext::extensions’s doc) is threaded through exactly this
struct rather than as a brand-new parameter: ClientIpContext is
already the one extractor every REST/RPC dispatch fn in the
generated code accepts, so reusing it means every transport picks the
new field up for free instead of needing its own separate threading
(and its own separate chance to be forgotten).
Cost, and why it can’t be avoided by borrowing instead of cloning:
extensions.clone() runs unconditionally on every request, on every
transport, whether or not the installed AuthProvider ever reads
RequestContext::extensions. This can’t be sidestepped by threading a
&'a http::Extensions instead: FromRequestParts::from_request_parts
returns an owned Self with no lifetime tied to its &mut Parts
argument (axum-core 0.5.6’s trait signature — Self: Sized, no
borrow), and by the time a generated dispatch fn runs, the Parts
this extractor was called from no longer exists as a distinct value
for anything to borrow from — axum’s tuple-extractor machinery
recombines it with the body for the next extractor in the parameter
list. Getting a genuine &'a Extensions would require every generated
handler to take one axum::extract::Request parameter and hand-roll
every other extraction (headers, path, query, body) that today comes
free from typed extractors — a rewrite of the entire handler-codegen
surface, not a local fix here. This is exactly the same constraint
HeaderMap’s own axum-core extractor is already under (Ok(parts. headers.clone()) — axum-core-0.5.6/src/extract/request_parts.rs),
which every generated dispatch fn already accepts unconditionally, so
this field’s cost is the same class the framework already pays, not a
new one. Benchmarked (tests_extensions_clone_cost.rs, run via
cargo test -p cratestack-axum -- --ignored --nocapture extensions_clone_cost) against a realistic served-router extensions
map (ConnectInfo<SocketAddr> + a 3-entry-allowlist
TrustedProxyConfig): roughly 30-150ns/clone in a --release build
(200,000-iteration loop, several runs on a loaded dev machine), the
same order of magnitude as — and never measured meaningfully above —
the HeaderMap clone (also ~30-150ns across the same runs) every
generated dispatch fn already pays unconditionally for a representative
4-header set. Both are noise next to a real request’s network/DB round
trip (microseconds-to-milliseconds). Debug builds measure ~265ns for
both (same relationship, uniformly slower), so this isn’t a
debug-vs-release artifact. Most axum-ecosystem extensions (ConnectInfo, MatchedPath,
a tracing::Span) are Copy or Arc-backed and cheap to clone,
but http::Extensions::clone() is a deep clone of the typemap: a
consumer who inserts a large non-Arc-backed value into extensions
(a big Vec/String/owned buffer, say) now pays that clone’s real
cost on every single request, not just when read — size your own
extension values accordingly, or wrap them in Arc before inserting.
A hand-written FromRequestParts impl rather than Option<Extension<T>>/
Option<ConnectInfo<T>> extractor parameters: axum 0.8 only extends its
blanket Option<T>: FromRequestParts impl to types implementing the
separate OptionalFromRequestParts trait, which neither Extension<T>
nor ConnectInfo<T> implements — so those two, wrapped in Option,
are not valid extractor parameter types on this axum version. Reading
Parts::extensions directly (via the infallible Extensions extractor
axum-core itself provides) sidesteps that entirely and never fails.
Fields§
§trusted_proxy: Option<TrustedProxyConfig>§peer: Option<SocketAddr>§extensions: ExtensionsImplementations§
Source§impl ClientIpContext
impl ClientIpContext
Sourcepub fn from_extensions(extensions: &Extensions) -> ClientIpContext
pub fn from_extensions(extensions: &Extensions) -> ClientIpContext
Build directly from a raw http::Extensions map — the shared
construction path used both by non-axum test harnesses that build
requests by hand and by the FromRequestParts impl below, which
delegates here rather than duplicating the field-by-field
extraction logic.
Trait Implementations§
Source§impl Clone for ClientIpContext
impl Clone for ClientIpContext
Source§fn clone(&self) -> ClientIpContext
fn clone(&self) -> ClientIpContext
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ClientIpContext
impl Debug for ClientIpContext
Source§impl Default for ClientIpContext
impl Default for ClientIpContext
Source§fn default() -> ClientIpContext
fn default() -> ClientIpContext
Source§impl<S> FromRequestParts<S> for ClientIpContext
impl<S> FromRequestParts<S> for ClientIpContext
Source§type Rejection = Infallible
type Rejection = Infallible
Source§async fn from_request_parts(
parts: &mut Parts,
_state: &S,
) -> Result<ClientIpContext, <ClientIpContext as FromRequestParts<S>>::Rejection>
async fn from_request_parts( parts: &mut Parts, _state: &S, ) -> Result<ClientIpContext, <ClientIpContext as FromRequestParts<S>>::Rejection>
Auto Trait Implementations§
impl !RefUnwindSafe for ClientIpContext
impl !UnwindSafe for ClientIpContext
impl Freeze for ClientIpContext
impl Send for ClientIpContext
impl Sync for ClientIpContext
impl Unpin for ClientIpContext
impl UnsafeUnpin for ClientIpContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<S, T> FromRequest<S, ViaParts> for T
impl<S, T> FromRequest<S, ViaParts> for T
§type Rejection = <T as FromRequestParts<S>>::Rejection
type Rejection = <T as FromRequestParts<S>>::Rejection
§fn from_request(
req: Request<Body>,
state: &S,
) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>
fn from_request( req: Request<Body>, state: &S, ) -> impl Future<Output = Result<T, <T as FromRequest<S, ViaParts>>::Rejection>>
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<'src, T> IntoMaybe<'src, T> for Twhere
T: 'src,
impl<'src, T> IntoMaybe<'src, T> for Twhere
T: 'src,
impl<T> OrderedSeq<'_, T> for Twhere
T: Clone,
§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute] value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi [Quirk] value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition] value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
§type Iter<'a> = Once<&'a T>
where
T: 'a
type Iter<'a> = Once<&'a T> where T: 'a
§fn contains(&self, val: &T) -> boolwhere
T: PartialEq,
fn contains(&self, val: &T) -> boolwhere
T: PartialEq,
§fn to_maybe_ref<'b>(item: <T as Seq<'p, T>>::Item<'b>) -> Maybe<T, &'p T>where
'p: 'b,
fn to_maybe_ref<'b>(item: <T as Seq<'p, T>>::Item<'b>) -> Maybe<T, &'p T>where
'p: 'b,
MaybeRef].