1#[cfg(all(feature = "server", test))]
9use std::future::Future;
10
11#[cfg(feature = "server")]
13pub fn request_parts() -> Option<http::request::Parts> {
14 leptos::prelude::use_context::<http::request::Parts>()
15}
16
17#[cfg(feature = "server")]
19pub fn request_headers() -> Option<http::HeaderMap> {
20 request_parts().map(|parts| parts.headers)
21}
22
23#[cfg(feature = "server")]
25pub fn request_extension<T: Clone + Send + Sync + 'static>() -> Option<T> {
26 request_parts().and_then(|parts| parts.extensions.get::<T>().cloned())
27}
28
29#[cfg(feature = "server")]
31pub fn append_response_header(name: http::HeaderName, value: http::HeaderValue) {
32 if let Some(options) = leptos::prelude::use_context::<leptos_axum::ResponseOptions>() {
33 options.append_header(name, value);
34 }
35}
36
37pub fn set_status(code: u16) {
44 #[cfg(feature = "server")]
45 if let Some(options) = leptos::prelude::use_context::<leptos_axum::ResponseOptions>() {
46 if let Ok(status) = http::StatusCode::from_u16(code) {
47 options.set_status(status);
48 }
49 }
50 #[cfg(not(feature = "server"))]
51 let _ = code;
52}
53
54#[cfg(all(feature = "server", test))]
56pub async fn scope_with_request<F: Future>(parts: http::request::Parts, fut: F) -> F::Output {
57 use leptos::prelude::{provide_context, Owner};
58
59 let owner = Owner::new();
60 owner
61 .with(|| {
62 provide_context(parts);
63 provide_context(leptos_axum::ResponseOptions::default());
64 leptos::reactive::computed::ScopedFuture::new(fut)
65 })
66 .await
67}
68
69#[cfg(all(test, feature = "server"))]
70mod tests {
71 use super::*;
72
73 fn parts() -> http::request::Parts {
74 let mut request = http::Request::builder()
75 .header("cookie", "session=abc")
76 .body(())
77 .unwrap();
78 request.extensions_mut().insert(7_u32);
79 request.into_parts().0
80 }
81
82 #[tokio::test]
83 async fn scope_exposes_request_headers_and_extensions() {
84 let (cookie, extension, status_ok) = scope_with_request(parts(), async {
85 set_status(404);
86 let cookie = request_headers()
87 .and_then(|headers| headers.get("cookie").cloned())
88 .map(|value| value.to_str().unwrap().to_string());
89 let status = leptos::prelude::use_context::<leptos_axum::ResponseOptions>()
90 .map(|options| options.0.read().unwrap().status);
91 (
92 cookie,
93 request_extension::<u32>(),
94 status == Some(Some(http::StatusCode::NOT_FOUND)),
95 )
96 })
97 .await;
98 assert_eq!(cookie.as_deref(), Some("session=abc"));
99 assert_eq!(extension, Some(7));
100 assert!(status_ok);
101 }
102
103 #[tokio::test]
104 async fn outside_a_request_everything_is_empty() {
105 assert!(request_parts().is_none());
106 assert!(request_headers().is_none());
107 assert_eq!(request_extension::<u32>(), None);
108 set_status(500);
109 }
110}