use std::{convert::Infallible, future::Future, pin::Pin};
use http_body_util::{BodyExt, Full};
use hyper::{Method, Request, Response, StatusCode, body::Incoming};
use log::{error, trace};
use serde_json::Value;
use super::{error::XmrigProxyError, inner::InnerService};
const LOG_TARGET: &str = "minotari::base_node::xmrig_proxy::service";
pub type ProxyBody = Full<bytes::Bytes>;
pub fn json_response(status: StatusCode, body: &Value) -> Result<Response<ProxyBody>, XmrigProxyError> {
let body_bytes = serde_json::to_vec(body)?;
Ok(Response::builder()
.status(status)
.header("Content-Type", "application/json")
.body(Full::new(bytes::Bytes::from(body_bytes)))
.expect("valid response"))
}
#[derive(Clone)]
pub struct XmrigProxyService {
inner: InnerService,
}
impl XmrigProxyService {
pub fn new(inner: InnerService) -> Self {
Self { inner }
}
}
impl hyper::service::Service<Request<Incoming>> for XmrigProxyService {
type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Response<ProxyBody>, Infallible>> + Send>>;
type Response = Response<ProxyBody>;
fn call(&self, req: Request<Incoming>) -> Self::Future {
let inner = self.inner.clone();
Box::pin(async move {
let method = req.method().clone();
let path = req.uri().path().to_string();
trace!(target: LOG_TARGET, "{method} {path}");
let result = if method == Method::GET {
inner.handle_get(&path).await
} else {
match req.into_body().collect().await {
Ok(collected) => inner.handle(collected.to_bytes()).await,
Err(e) => {
error!(target: LOG_TARGET, "Failed to collect request body: {e}");
Err(XmrigProxyError::InvalidRequest(e.to_string()))
},
}
};
Ok(match result {
Ok(response) => response,
Err(e) => {
error!(target: LOG_TARGET, "Handler error: {e}");
Response::builder()
.status(e.status_code())
.header("Content-Type", "application/json")
.body(Full::new(bytes::Bytes::from(
serde_json::to_vec(&serde_json::json!({
"jsonrpc": "2.0",
"id": -1,
"error": {"code": -32603, "message": e.to_string()},
}))
.unwrap_or_default(),
)))
.expect("valid error response")
},
})
})
}
}