1use axum::extract::FromRequestParts;
9use axum::http::request::Parts;
10use std::future::Future;
11use std::sync::Arc;
12use tracing::Span;
13
14use crate::ports::Defer;
15use crate::problem::Problem;
16
17#[derive(Clone)]
21pub struct Scope {
22 pub request_id: String,
23 pub defer: Arc<dyn Defer>,
24 pub span: Span,
25}
26
27impl std::fmt::Debug for Scope {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 f.debug_struct("Scope")
30 .field("request_id", &self.request_id)
31 .field("span", &self.span.metadata().map(tracing::Metadata::name))
32 .finish_non_exhaustive()
33 }
34}
35
36impl<S> FromRequestParts<S> for Scope
37where
38 S: Send + Sync,
39{
40 type Rejection = Problem;
41
42 fn from_request_parts(
43 parts: &mut Parts,
44 _state: &S,
45 ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send {
46 std::future::ready(
47 parts
48 .extensions
49 .get::<Scope>()
50 .cloned()
51 .ok_or_else(Problem::internal),
52 )
53 }
54}