2026-01-24 22:59:20 +00:00
|
|
|
use crate::api::rpc::RpcHandler;
|
|
|
|
|
use crate::config::Config;
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use http_body_util::{BodyExt, Full};
|
|
|
|
|
use hyper::body::Bytes;
|
|
|
|
|
use hyper::{Method, Request, Response, StatusCode};
|
|
|
|
|
use hyper_util::rt::TokioIo;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
use tracing::debug;
|
|
|
|
|
|
|
|
|
|
pub struct ApiHandler {
|
|
|
|
|
config: Config,
|
|
|
|
|
rpc_handler: Arc<RpcHandler>,
|
|
|
|
|
// Add other handlers here (websocket, static files, etc.)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ApiHandler {
|
|
|
|
|
pub async fn new(config: Config) -> Result<Self> {
|
|
|
|
|
let rpc_handler = Arc::new(RpcHandler::new(config.clone()).await?);
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
config,
|
|
|
|
|
rpc_handler,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 23:18:24 +00:00
|
|
|
pub async fn handle_request<B>(&self, req: Request<B>) -> Result<Response<Full<Bytes>>>
|
|
|
|
|
where
|
|
|
|
|
B: http_body::Body<Data = Bytes> + Send + 'static,
|
|
|
|
|
B::Error: std::fmt::Display,
|
|
|
|
|
{
|
2026-01-24 22:59:20 +00:00
|
|
|
let path = req.uri().path();
|
|
|
|
|
let method = req.method();
|
|
|
|
|
|
2026-01-24 23:18:24 +00:00
|
|
|
// Convert Incoming body to bytes using http_body_util::BodyExt
|
2026-01-24 22:59:20 +00:00
|
|
|
let (parts, body) = req.into_parts();
|
2026-01-24 23:18:24 +00:00
|
|
|
// hyper::body::Incoming implements http_body::Body, and BodyExt extends it
|
2026-01-24 23:09:46 +00:00
|
|
|
use http_body_util::BodyExt;
|
2026-01-24 23:18:24 +00:00
|
|
|
let collected = body.collect().await
|
2026-01-24 23:09:46 +00:00
|
|
|
.map_err(|_e| anyhow::anyhow!("Failed to read body"))?;
|
2026-01-24 22:59:20 +00:00
|
|
|
let body_bytes = collected.to_bytes();
|
|
|
|
|
|
|
|
|
|
// Reconstruct request with Full<Bytes> body for RPC handler
|
|
|
|
|
let req_with_bytes = Request::from_parts(parts, Full::new(body_bytes));
|
|
|
|
|
|
|
|
|
|
debug!("{} {}", method, path);
|
|
|
|
|
|
|
|
|
|
// Route requests
|
2026-01-24 23:09:46 +00:00
|
|
|
match (method, path.as_str()) {
|
2026-01-24 23:18:24 +00:00
|
|
|
(&Method::POST, "/rpc/v1") => {
|
2026-01-24 22:59:20 +00:00
|
|
|
self.rpc_handler.handle(req_with_bytes).await
|
|
|
|
|
}
|
2026-01-24 23:18:24 +00:00
|
|
|
(&Method::GET, "/health") => {
|
2026-01-24 22:59:20 +00:00
|
|
|
Ok(Response::builder()
|
|
|
|
|
.status(StatusCode::OK)
|
|
|
|
|
.body(Full::new(Bytes::from("OK")))
|
|
|
|
|
.unwrap())
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
Ok(Response::builder()
|
|
|
|
|
.status(StatusCode::NOT_FOUND)
|
|
|
|
|
.body(Full::new(Bytes::from("Not Found")))
|
|
|
|
|
.unwrap())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|