use crate::transport::http::core::{
context::HttpContext, engine::HttpEngine, handlers, types::SseResponse,
};
use ::volga::{
HttpRequest, HttpResult,
auth::{Bearer, BearerTokenService},
di::Dc,
error::Error as VolgaError,
headers::AUTHORIZATION,
http::sse::Message as SseMessage,
sse,
};
use std::sync::Arc;
use super::engine::VolgaEngine;
use crate::auth::Claims;
use crate::transport::http::core::types::DefaultClaims;
fn decode_claims(
bts: Option<BearerTokenService>,
headers: &http::HeaderMap,
) -> Option<DefaultClaims> {
let bts = bts?;
let header = headers.get(AUTHORIZATION)?;
let bearer = Bearer::try_from(header).ok()?;
bts.decode::<DefaultClaims>(bearer).ok()
}
pub(crate) async fn post(req: HttpRequest) -> HttpResult {
let manager: Dc<Arc<HttpContext>> = req.extract()?;
let bts: Option<BearerTokenService> = req.extract()?;
let mut neutral = VolgaEngine::adapt_request(req)
.await
.map_err(to_volga_err)?;
if let Some(claims) = decode_claims(bts, neutral.headers()) {
let claims: Arc<dyn Claims> = Arc::new(claims);
neutral.extensions_mut().insert(claims);
}
let resp = handlers::handle_post(neutral, &manager).await;
VolgaEngine::adapt_response(resp)
}
pub(crate) async fn delete(req: HttpRequest) -> HttpResult {
let manager: Dc<Arc<HttpContext>> = req.extract()?;
let neutral = VolgaEngine::adapt_request(req)
.await
.map_err(to_volga_err)?;
let resp = handlers::handle_delete(neutral, &manager).await;
VolgaEngine::adapt_response(resp)
}
pub(crate) async fn get(req: HttpRequest) -> HttpResult {
let manager: Dc<Arc<HttpContext>> = req.extract()?;
let outcome = handlers::dispatch_get_sse::<VolgaEngine>(req, &manager)
.await
.map_err(to_volga_err)?;
match outcome {
SseResponse::Stream { headers, stream } => {
let session_id = headers
.get(handlers::MCP_SESSION_ID)
.and_then(|v| v.to_str().ok())
.map(str::to_owned);
let stream = futures_util::StreamExt::map(stream, Ok::<SseMessage, VolgaError>);
if let Some(id) = session_id {
sse!(stream; [(handlers::MCP_SESSION_ID, id)])
} else {
sse!(stream)
}
}
SseResponse::Status(resp) => VolgaEngine::adapt_response(resp),
}
}
fn to_volga_err(err: crate::error::Error) -> VolgaError {
VolgaError::server_error(err.to_string())
}