use std::convert::Infallible;
use std::future::Future;
use std::pin::Pin;
use tower::Layer;
use crate::application::{Application, ProxyFn};
use crate::axum::body::Body;
use crate::axum::http::Response;
use crate::proxy::ProxyLayer;
use crate::routing::Routes;
#[cfg(feature = "observe")]
use crate::observe::{HttpLayer, RequestIdLayer};
type BoxFuture = Pin<Box<dyn Future<Output = Result<Response<Body>, Infallible>> + Send>>;
#[cfg(feature = "inertia")]
use crate::inertia::InertiaLayer;
#[cfg(feature = "pages")]
use crate::pages::MaintenanceLayer;
pub(crate) fn assemble_router(app: Application<()>) -> (Routes<()>, Option<ProxyFn>) {
let Application {
routes,
proxy,
bind_address: _,
port: _,
#[cfg(feature = "inertia")]
inertia_config,
#[cfg(feature = "inertia")]
page_contracts: _,
#[cfg(feature = "pages")]
pages,
#[cfg(feature = "pages")]
maintenance_guard,
#[cfg(feature = "db")]
database: _,
#[cfg(feature = "cache")]
cache_config: _,
#[cfg(feature = "storage")]
storage_config: _,
#[cfg(feature = "mail")]
mail_config: _,
#[cfg(feature = "jobs")]
jobs_registry: _,
#[cfg(feature = "jobs")]
worker_config: _,
#[cfg(feature = "dx")]
error_mapping,
#[cfg(feature = "dev-proxy")]
dev_proxy_endpoint: _,
} = app;
#[cfg(any(
feature = "pages",
feature = "inertia",
feature = "observe",
feature = "dx"
))]
let mut router = routes;
#[cfg(not(any(
feature = "pages",
feature = "inertia",
feature = "observe",
feature = "dx"
)))]
let router = routes;
#[cfg(feature = "pages")]
{
let pages = pages.unwrap_or_default();
router = router.fallback_service(pages.not_found_service());
}
#[cfg(feature = "observe")]
{
router =
router
.route_layer(HttpLayer::new())
.route_layer(crate::axum::middleware::from_fn(
crate::pipeline::matched_route::set_matched_route,
));
}
#[cfg(feature = "dx")]
{
if let Some(map) = error_mapping {
router = router.layer(crate::pipeline::error_mapping::ErrorMappingLayer::new(
Some(map),
));
}
}
#[cfg(feature = "inertia")]
{
if let Some(config) = inertia_config {
router = router.layer(InertiaLayer::new(config));
}
}
#[cfg(feature = "pages")]
{
if let Some(guard) = maintenance_guard {
router = router.layer(MaintenanceLayer::new(guard));
}
}
(router, proxy)
}
pub(crate) fn into_service(
app: Application<()>,
) -> impl tower::Service<
crate::axum::extract::Request<Body>,
Response = Response<Body>,
Error = Infallible,
Future = BoxFuture,
> + Clone
+ Send
+ 'static {
#[cfg(feature = "dev-proxy")]
let dev_proxy_endpoint = app.dev_proxy_endpoint.clone();
let (router, proxy) = assemble_router(app);
let router_service = router.into_service::<Body>();
let with_proxy = ProxyLayer::new(proxy).layer(router_service);
#[cfg(feature = "observe")]
let composed = RequestIdLayer::new().layer(with_proxy);
#[cfg(not(feature = "observe"))]
let composed = with_proxy;
#[cfg(feature = "dev-proxy")]
{
let endpoint = dev_proxy_endpoint.or_else(crate::dev_proxy::config::endpoint_from_env);
crate::dev_proxy::DevProxyLayer::new(endpoint).layer(composed)
}
#[cfg(not(feature = "dev-proxy"))]
{
composed
}
}