ResponseOptions support
This commit is contained in:
parent
402d6297f4
commit
40c1f38a07
|
@ -15,6 +15,7 @@ axum = { version = "0.7", default-features = false, features = [
|
||||||
"matched-path",
|
"matched-path",
|
||||||
] }
|
] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
http = "1"
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
leptos = { workspace = true, features = ["nonce", "hydration"] }
|
leptos = { workspace = true, features = ["nonce", "hydration"] }
|
||||||
server_fn = { workspace = true, features = ["axum-no-default"] }
|
server_fn = { workspace = true, features = ["axum-no-default"] }
|
||||||
|
@ -36,6 +37,7 @@ tokio = { version = "1", features = ["net"] }
|
||||||
[features]
|
[features]
|
||||||
wasm = []
|
wasm = []
|
||||||
default = ["tokio/fs", "tokio/sync"]
|
default = ["tokio/fs", "tokio/sync"]
|
||||||
|
nonce = ["leptos/nonce"]
|
||||||
#experimental-islands = ["leptos_integration_utils/experimental-islands"]
|
#experimental-islands = ["leptos_integration_utils/experimental-islands"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
@ -48,6 +48,7 @@ use hydration_context::SsrSharedContext;
|
||||||
use leptos::{
|
use leptos::{
|
||||||
config::LeptosOptions,
|
config::LeptosOptions,
|
||||||
context::{provide_context, use_context},
|
context::{provide_context, use_context},
|
||||||
|
nonce::use_nonce,
|
||||||
reactive_graph::{computed::ScopedFuture, owner::Owner},
|
reactive_graph::{computed::ScopedFuture, owner::Owner},
|
||||||
IntoView,
|
IntoView,
|
||||||
};
|
};
|
||||||
|
@ -738,16 +739,16 @@ where
|
||||||
// run app
|
// run app
|
||||||
let app = app_fn();
|
let app = app_fn();
|
||||||
|
|
||||||
// TODO nonce
|
let nonce = use_nonce()
|
||||||
|
.as_ref()
|
||||||
|
.map(|nonce| format!(" nonce=\"{nonce}\""))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let shared_context = Owner::current_shared_context().unwrap();
|
let shared_context = Owner::current_shared_context().unwrap();
|
||||||
let chunks = Box::new(move || {
|
let chunks = Box::new(move || {
|
||||||
Box::pin(
|
Box::pin(shared_context.pending_data().unwrap().map(
|
||||||
shared_context
|
move |chunk| format!("<script{nonce}>{chunk}</script>"),
|
||||||
.pending_data()
|
))
|
||||||
.unwrap()
|
|
||||||
.map(|chunk| format!("<script>{chunk}</script>")),
|
|
||||||
)
|
|
||||||
as Pin<Box<dyn Stream<Item = String> + Send>>
|
as Pin<Box<dyn Stream<Item = String> + Send>>
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -762,10 +763,27 @@ where
|
||||||
stream_builder(app, chunks)
|
stream_builder(app, chunks)
|
||||||
}));
|
}));
|
||||||
let stream = stream.await;
|
let stream = stream.await;
|
||||||
let stream = meta_context.inject_meta_context(stream).await;
|
let mut stream =
|
||||||
|
Box::pin(meta_context.inject_meta_context(stream).await);
|
||||||
|
|
||||||
// TODO test this
|
// wait for the first chunk of the stream, then set the status and headers
|
||||||
/*if let Some(status) = res_options.status {
|
let first_chunk = stream.next().await.unwrap_or_default();
|
||||||
|
|
||||||
|
let mut res = Html(Body::from_stream(Sandboxed::new(
|
||||||
|
once(async move { first_chunk })
|
||||||
|
.chain(stream)
|
||||||
|
.map(|chunk| Ok(chunk) as Result<String, std::io::Error>)
|
||||||
|
// drop the owner, cleaning up the reactive runtime,
|
||||||
|
// once the stream is over
|
||||||
|
.chain(once(async move {
|
||||||
|
drop(owner);
|
||||||
|
Ok(Default::default())
|
||||||
|
})),
|
||||||
|
)))
|
||||||
|
.into_response();
|
||||||
|
|
||||||
|
let mut res_options = res_options.0.read();
|
||||||
|
if let Some(status) = res_options.status {
|
||||||
*res.status_mut() = status
|
*res.status_mut() = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,19 +799,9 @@ where
|
||||||
header::CONTENT_TYPE,
|
header::CONTENT_TYPE,
|
||||||
HeaderValue::from_str("text/html; charset=utf-8").unwrap(),
|
HeaderValue::from_str("text/html; charset=utf-8").unwrap(),
|
||||||
);
|
);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
Html(Body::from_stream(Sandboxed::new(
|
res
|
||||||
stream
|
|
||||||
.map(|chunk| Ok(chunk) as Result<String, std::io::Error>)
|
|
||||||
// drop the owner, cleaning up the reactive runtime,
|
|
||||||
// once the stream is over
|
|
||||||
.chain(once(async move {
|
|
||||||
drop(owner);
|
|
||||||
Ok(Default::default())
|
|
||||||
})),
|
|
||||||
)))
|
|
||||||
.into_response()
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1155,6 +1163,14 @@ where
|
||||||
.with(|| {
|
.with(|| {
|
||||||
// stub out a path for now
|
// stub out a path for now
|
||||||
provide_context(RequestUrl::new(""));
|
provide_context(RequestUrl::new(""));
|
||||||
|
let (mock_parts, _) =
|
||||||
|
http::Request::new(Body::from("")).into_parts();
|
||||||
|
provide_contexts(
|
||||||
|
"",
|
||||||
|
&Default::default(),
|
||||||
|
mock_parts,
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
additional_context();
|
additional_context();
|
||||||
RouteList::generate(&app_fn)
|
RouteList::generate(&app_fn)
|
||||||
})
|
})
|
||||||
|
@ -1498,12 +1514,7 @@ where
|
||||||
let mut router = self;
|
let mut router = self;
|
||||||
|
|
||||||
// register server functions
|
// register server functions
|
||||||
println!(
|
|
||||||
"server fn paths are {:?}",
|
|
||||||
server_fn::axum::server_fn_paths().collect::<Vec<_>>()
|
|
||||||
);
|
|
||||||
for (path, method) in server_fn::axum::server_fn_paths() {
|
for (path, method) in server_fn::axum::server_fn_paths() {
|
||||||
println!("registering {path}");
|
|
||||||
let cx_with_state = cx_with_state.clone();
|
let cx_with_state = cx_with_state.clone();
|
||||||
let handler = move |req: Request<Body>| async move {
|
let handler = move |req: Request<Body>| async move {
|
||||||
handle_server_fns_with_context(cx_with_state, req).await
|
handle_server_fns_with_context(cx_with_state, req).await
|
||||||
|
|
Loading…
Reference in New Issue