fix(server): hyper knobs, decoy fidelity, cache + builder fixes (SRV-04..SRV-10)

- SRV-04: TokioTimer on h1+h2 builder, header_read_timeout 10s,
  h1 keep-alive on, h2 keep-alive 30s/10s; concurrency boundary documented
- SRV-05: with_decoy rebuild keeps extra routes (clone, not take)
- SRV-07: method_not_allowed_fallback serves the nginx-shaped 405
- SRV-08: UTF-8 percent-decoding, literal '+', tokio::fs syscalls
- SRV-09: /openapi.json cached at construction, generic 500 body,
  to_openapi returns Result (expect removed)
- SRV-10: ChannelsPolicy extension injection point on the WS upgrade;
  single token resolution via route ordering (WS layer before the
  router-wide auth route_layer)

Verification: cargo test 265 passed; --all-features server::/to_openapi::
green; clippy + fmt clean on touched files (remaining tree noise is a
parallel agent's in-flight from_mcp/from_wss/forward work)
This commit is contained in:
2026-08-29 10:47:44 +00:00
parent 1dc1d5af4f
commit 314472012d
10 changed files with 503 additions and 86 deletions
+10 -1
View File
@@ -25,12 +25,14 @@ pub enum DecoyConfig {
/// State embedded in the axum `Router`: the registry and identity
/// provider every request handler reaches through the router state, plus
/// the decoy config for the fallback.
/// the decoy config for the fallback and the pre-serialized
/// `/openapi.json` projection cache (SRV-09).
#[derive(Clone)]
pub(crate) struct RouterState {
pub(crate) registry: Arc<OperationRegistry>,
pub(crate) identity_provider: Arc<dyn IdentityProvider>,
pub(crate) decoy: DecoyConfig,
pub(crate) openapi_doc: crate::server::adapter::CachedOpenAPIDoc,
}
impl axum::extract::FromRef<RouterState> for DecoyConfig {
@@ -51,6 +53,12 @@ impl axum::extract::FromRef<RouterState> for Arc<dyn IdentityProvider> {
}
}
impl axum::extract::FromRef<RouterState> for crate::server::adapter::CachedOpenAPIDoc {
fn from_ref(state: &RouterState) -> Self {
state.openapi_doc.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -68,6 +76,7 @@ mod tests {
decoy: DecoyConfig::Redirect {
to: "https://example.com".to_string(),
},
openapi_doc: crate::server::adapter::CachedOpenAPIDoc::new(&OperationRegistry::new()),
};
let extracted: DecoyConfig = axum::extract::FromRef::from_ref(&state);
assert!(matches!(extracted, DecoyConfig::Redirect { .. }));