use std::sync::Arc;
use axum::{
Json,
extract::{FromRequestParts, OriginalUri},
http::{StatusCode, header::LOCATION},
response::{Html, IntoResponse, Response},
};
use crate::{
extension::InertiaExtension,
inertia::{self, RenderResponse},
};
pub async fn driver(mut parts: axum::http::request::Parts, mut res: Response) -> Response {
let res_exts = res.extensions_mut();
let Some(inertia_ext): Option<Arc<InertiaExtension>> = res_exts.remove() else {
tracing::error!("extension not set, handler likely failed");
return res;
};
let (mut res_parts, _body_unsused_we_overwrite) = res.into_parts();
if let Some(redirect) = inertia_ext.take_redirect() {
res_parts.status = StatusCode::SEE_OTHER;
res_parts.headers.insert(LOCATION, redirect);
return res_parts.into_response().into_response();
}
let component = match inertia_ext.component() {
Some(component) => component,
None => {
tracing::warn!(
"component nor redirect set, this is likely caused by lack of an error handler middleware"
);
return res_parts.into_response().into_response();
}
};
let props = inertia_ext.take_props();
let version = inertia_ext.version();
let original_uri = OriginalUri::from_request_parts(&mut parts, &())
.await
.unwrap();
let render_response = RenderResponse::builder()
.clear_history(inertia_ext.get_clear_history())
.encrypt_history(inertia_ext.get_encrypt_history())
.url(original_uri.to_string())
.version(version.expect("version never set"))
.component(component)
.props(&props)
.build();
res_parts
.headers
.append("Vary", "X-Inertia".try_into().unwrap());
if inertia::RequestHeaders::from(&parts.headers).x_inertia() {
res_parts
.headers
.append("X-Inertia", "true".try_into().unwrap());
(res_parts, Json(render_response)).into_response()
} else {
let html = inertia_ext.render_html(render_response).await;
Html(html).into_response()
}
}