1use axum::{
2 extract::FromRequestParts,
3 http::StatusCode,
4 http::request::Parts,
5 response::{IntoResponse, Response},
6};
7use std::fmt;
8
9#[derive(Debug, Clone)]
24pub struct NovaState<S>(pub S);
25
26impl<S, State> FromRequestParts<State> for NovaState<S>
27where
28 S: Clone + Send + Sync + 'static,
29 State: Send + Sync,
30{
31 type Rejection = NovaStateRejection;
32
33 fn from_request_parts(
34 parts: &mut Parts,
35 _state: &State,
36 ) -> impl std::future::Future<Output = Result<Self, Self::Rejection>> + Send {
37 let result = parts
38 .extensions
39 .get::<S>()
40 .cloned()
41 .map(NovaState)
42 .ok_or(NovaStateRejection);
43
44 async move { result }
45 }
46}
47
48#[derive(Debug)]
54pub struct NovaStateRejection;
55
56impl fmt::Display for NovaStateRejection {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(
59 f,
60 "Application state is not present in request extensions. \
61 Ensure you added the state via `NovaApp::new()` and did not remove the `Extension` layer."
62 )
63 }
64}
65
66impl std::error::Error for NovaStateRejection {}
67
68impl IntoResponse for NovaStateRejection {
69 fn into_response(self) -> Response {
70 (
71 StatusCode::INTERNAL_SERVER_ERROR,
72 "Internal server error: application state missing",
73 )
74 .into_response()
75 }
76}