#![cfg(all(feature = "executor_tokio", feature = "framework_axum"))]
use std::prelude::v1::*;
use core::error::Error;
use product_os_net::SocketAddr;
use hyper::service::Service;
use product_os_async_executor::{Executor, TokioExecutor};
use product_os_router::{Request, Service as RouterService, Router };
pub async fn create_http_tokio_service(socket_address: SocketAddr, router: Router, with_connect_info: bool) -> Result<(), Box<dyn Error + Send + Sync>> {
tracing::info!("Starting HTTP server listening on {}", socket_address);
let listener = tokio::net::TcpListener::bind(socket_address).await
.map_err(|e| -> Box<dyn Error + Send + Sync> { Box::new(e) })?;
loop {
let (cnx, addr) = match listener.accept().await {
Ok(conn) => conn,
Err(e) => {
tracing::error!("Failed to accept connection: {:?}", e);
continue;
}
};
match with_connect_info {
true => {
let make_service = hyper_util::service::TowerToHyperService::new(router.clone().into_make_service_with_connect_info::<SocketAddr>());
let tower_service = match make_service.call(socket_address).await {
Ok(svc) => svc,
Err(e) => {
tracing::error!("Failed to create tower service: {:?}", e);
continue;
}
};
tokio::spawn(async move {
let stream = hyper_util::rt::TokioIo::new(cnx);
let hyper_service = hyper::service::service_fn(move |request: Request<hyper::body::Incoming>| {
tower_service.clone().call(request)
});
match TokioExecutor::context_sync() {
Ok(executor) => {
let _ret = hyper_util::server::conn::auto::Builder::new(executor)
.serve_connection_with_upgrades(stream, hyper_service)
.await;
}
Err(e) => tracing::error!("Failed to get executor for connection from {}: {:?}", addr, e)
}
});
}
false => {
let tower_service = router.clone();
tokio::spawn(async move {
let stream = hyper_util::rt::TokioIo::new(cnx);
let hyper_service = hyper::service::service_fn(move |request: Request<hyper::body::Incoming>| {
tower_service.clone().call(request)
});
match TokioExecutor::context_sync() {
Ok(executor) => {
let _ret = hyper_util::server::conn::auto::Builder::new(executor)
.serve_connection_with_upgrades(stream, hyper_service)
.await;
}
Err(e) => tracing::error!("Failed to get executor for connection from {}: {:?}", addr, e)
}
});
}
}
}
}