feat(http): complete to_openapi gateway projection with error fidelity and route wiring

Refine to_openapi to project operation-level errors (with http_status)
onto /call and /subscribe responses via oneOf merge with protocol-level
errors, preserving HTTP_<status> prefix codes without collision. Fix
BTreeMap→serde_json::Map for Value::Object compatibility. Wire GET
/openapi.json route test. Apply cargo fmt across the crate.
This commit is contained in:
2026-07-01 20:11:09 +00:00
parent 2695a19502
commit dd6aacc598
17 changed files with 1227 additions and 683 deletions

View File

@@ -80,11 +80,12 @@ where
{
type Rejection = Infallible;
async fn from_request_parts(
parts: &mut Parts,
_state: &S,
) -> Result<Self, Self::Rejection> {
let identity = parts.extensions.get::<Option<Identity>>().cloned().flatten();
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let identity = parts
.extensions
.get::<Option<Identity>>()
.cloned()
.flatten();
Ok(ResolvedIdentity(identity))
}
}
@@ -174,15 +175,16 @@ mod tests {
assert!(identity.is_none());
}
async fn run_middleware(
idp: Arc<dyn IdentityProvider>,
request: Request,
) -> Response {
async fn run_middleware(idp: Arc<dyn IdentityProvider>, request: Request) -> Response {
let app: Router<()> = Router::new()
.route(
"/",
get(|req: Request| async move {
let identity = req.extensions().get::<Option<Identity>>().cloned().flatten();
let identity = req
.extensions()
.get::<Option<Identity>>()
.cloned()
.flatten();
if let Some(id) = identity {
(StatusCode::OK, id.id)
} else {
@@ -261,14 +263,12 @@ mod tests {
let app: Router<()> = Router::new()
.route(
"/",
get(
|ResolvedIdentity(identity): ResolvedIdentity| async move {
match identity {
Some(id) => (StatusCode::OK, id.id),
None => (StatusCode::OK, "none".to_string()),
}
},
),
get(|ResolvedIdentity(identity): ResolvedIdentity| async move {
match identity {
Some(id) => (StatusCode::OK, id.id),
None => (StatusCode::OK, "none".to_string()),
}
}),
)
.layer(from_fn_with_state(idp, bearer_auth_middleware));
@@ -287,14 +287,12 @@ mod tests {
let app: Router<()> = Router::new()
.route(
"/",
get(
|ResolvedIdentity(identity): ResolvedIdentity| async move {
match identity {
Some(id) => (StatusCode::OK, id.id),
None => (StatusCode::OK, "none".to_string()),
}
},
),
get(|ResolvedIdentity(identity): ResolvedIdentity| async move {
match identity {
Some(id) => (StatusCode::OK, id.id),
None => (StatusCode::OK, "none".to_string()),
}
}),
)
.layer(from_fn_with_state(idp, bearer_auth_middleware));
@@ -306,4 +304,4 @@ mod tests {
.unwrap();
assert_eq!(&bytes[..], b"none");
}
}
}