pub struct RequestContext;Expand description
Scoped identity and trace id of the current request, shared by every layer.
This is the single source of truth for “who is acting” and “which request is
this”. The HTTP adapter establishes the context before binding the
request (RequestModel::bind), so the binder, the handler, middleware and
the persistence layer all read the very same Arc<IdentityUser> and the very
same trace id — there is no second copy of sub and no way for audit and
handler code to disagree.
The trace id is the one the tracing middleware echoes in the x-trace-id
response header, so a handler that stamps it onto an audit row can be joined
with the access log line for the same request:
let trace_id = RequestContext::trace_id().map(|id| id.to_string());
audit.trace_id = trace_id;Background work (IHostedService, spawned tasks, timers) has no ambient
identity by default: identity() and operator_id() return None there,
which audit code must treat as the System principal. A background job that
acts on behalf of a user scopes that identity explicitly:
let identity = Arc::new(IdentityUser { id: "user-1".into(), ..Default::default() });
RequestContext::run(Some(identity), async move {
// audit here sees user-1
})
.await;Implementations§
Source§impl RequestContext
impl RequestContext
Sourcepub async fn run<F, R>(identity: Option<Arc<IdentityUser>>, f: F) -> Rwhere
F: Future<Output = R>,
pub async fn run<F, R>(identity: Option<Arc<IdentityUser>>, f: F) -> Rwhere
F: Future<Output = R>,
Run an async block with identity in scope.
Pass None for an anonymous request (or a system-initiated task); inside
f, identity() and operator_id() then return None.
An enclosing trace id is preserved: nesting a narrower identity scope (audit helpers do this) must not make the trace id disappear.
Sourcepub async fn run_with_trace<F, R>(
identity: Option<Arc<IdentityUser>>,
trace_id: Option<Arc<str>>,
f: F,
) -> Rwhere
F: Future<Output = R>,
pub async fn run_with_trace<F, R>(
identity: Option<Arc<IdentityUser>>,
trace_id: Option<Arc<str>>,
f: F,
) -> Rwhere
F: Future<Output = R>,
Run an async block with identity and trace_id in scope.
The HTTP adapter uses this: it passes the context’s
IHttpContext::trace_id so the
handler reads exactly the id emitted in the x-trace-id response header.
Pass None for a request that has no trace id.
Sourcepub fn identity() -> Option<Arc<IdentityUser>>
pub fn identity() -> Option<Arc<IdentityUser>>
The authenticated identity of the current request, if any.
Returns the very Arc the HTTP adapter created, so resolving the
identity twice never allocates a second copy.
Sourcepub fn trace_id() -> Option<Arc<str>>
pub fn trace_id() -> Option<Arc<str>>
The trace id of the current request, if the host assigned one.
Identical to the x-trace-id response header. None outside a request
scope (background work) and for hosts that do not run the tracing
middleware.
Sourcepub fn operator_id() -> Option<String>
pub fn operator_id() -> Option<String>
The current operator id (IdentityUser::id), if authenticated.
None for anonymous requests and for background work that did not scope
an identity — audit code should record those as System.