multiple fullstack nits/cleanups before release (#4852)
* feat: `:arg` syntax for serverfn * add better decode/encode verify message * allow catch-all query args * add rebind * implement websocket frames for `Streaming` * fix lazy init * wip... serverfnstate * wip... * wip: serverfns require Send/Sync, let's fix that * wip... * small cleanup * fix hang by actually spawning the tokio task * clippy * fix parameter catchall binding * fix lychee * doc tests
This commit is contained in:
1 parent
43373f0be7
commit
5559e463c8
27 files changed
+1395
-1097
No files matched your search
@@ -162,6 +162,20 @@ impl From<RequestError> for ServerFnError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ServerFnError> for HttpError {
|
||||
fn from(value: ServerFnError) -> Self {
|
||||
let status = StatusCode::from_u16(match &value {
|
||||
ServerFnError::ServerError { code, .. } => *code,
|
||||
_ => 500,
|
||||
})
|
||||
.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
|
||||
HttpError {
|
||||
status,
|
||||
message: Some(value.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HttpError> for ServerFnError {
|
||||
fn from(value: HttpError) -> Self {
|
||||
ServerFnError::ServerError {
|
||||
|
||||
@@ -25,6 +25,3 @@ pub use error::*;
|
||||
|
||||
pub mod httperror;
|
||||
pub use httperror::*;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct DioxusServerState {}
|
||||
@@ -9,10 +9,6 @@ use std::collections::HashSet;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
tokio::task_local! {
|
||||
static FULLSTACK_CONTEXT: FullstackContext;
|
||||
}
|
||||
|
||||
/// The context provided by dioxus fullstack for server-side rendering.
|
||||
///
|
||||
/// This context will only be set on the server during the initial streaming response
|
||||
@@ -21,10 +17,18 @@ tokio::task_local! {
|
||||
pub struct FullstackContext {
|
||||
// We expose the lock for request headers directly so it needs to be in a separate lock
|
||||
request_headers: Arc<RwLock<http::request::Parts>>,
|
||||
|
||||
// The rest of the fields are only held internally, so we can group them together
|
||||
lock: Arc<RwLock<FullstackContextInner>>,
|
||||
}
|
||||
|
||||
// `FullstackContext` is always set when either
|
||||
// 1. rendering the app via SSR
|
||||
// 2. handling a server function request
|
||||
tokio::task_local! {
|
||||
static FULLSTACK_CONTEXT: FullstackContext;
|
||||
}
|
||||
|
||||
pub struct FullstackContextInner {
|
||||
current_status: StreamingStatus,
|
||||
current_status_subscribers: HashSet<ReactiveContext>,
|
||||
@@ -78,6 +82,7 @@ impl FullstackContext {
|
||||
pub fn commit_initial_chunk(&mut self) {
|
||||
let mut lock = self.lock.write();
|
||||
lock.current_status = StreamingStatus::InitialChunkCommitted;
|
||||
|
||||
// The key type is mutable, but the hash is stable through mutations because we hash by pointer
|
||||
#[allow(clippy::mutable_key_type)]
|
||||
let subscribers = std::mem::take(&mut lock.current_status_subscribers);
|
||||
@@ -110,17 +115,23 @@ impl FullstackContext {
|
||||
FULLSTACK_CONTEXT.scope(self, fut).await
|
||||
}
|
||||
|
||||
/// Extract an extension from the current request.
|
||||
pub fn extension<T: Clone + Send + Sync + 'static>(&self) -> Option<T> {
|
||||
let lock = self.request_headers.read();
|
||||
lock.extensions.get::<T>().cloned()
|
||||
}
|
||||
|
||||
/// Extract an axum extractor from the current request.
|
||||
///
|
||||
/// The body of the request is always empty when using this method, as the body can only be consumed once in the server
|
||||
/// function extractors.
|
||||
pub async fn extract<T: FromRequest<(), M>, M>() -> Result<T, ServerFnError> {
|
||||
pub async fn extract<T: FromRequest<Self, M>, M>() -> Result<T, ServerFnError> {
|
||||
let this = Self::current()
|
||||
.ok_or_else(|| ServerFnError::new("No FullstackContext found".to_string()))?;
|
||||
|
||||
let parts = this.request_headers.read().clone();
|
||||
let request = axum_core::extract::Request::from_parts(parts, Default::default());
|
||||
match T::from_request(request, &()).await {
|
||||
match T::from_request(request, &this).await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => {
|
||||
let resp = err.into_response();
|
||||
@@ -255,7 +266,7 @@ pub fn commit_initial_chunk() {
|
||||
|
||||
/// Extract an axum extractor from the current request.
|
||||
#[deprecated(note = "Use FullstackContext::extract instead", since = "0.7.0")]
|
||||
pub fn extract<T: FromRequest<(), M>, M>(
|
||||
pub fn extract<T: FromRequest<FullstackContext, M>, M>(
|
||||
) -> impl std::future::Future<Output = Result<T, ServerFnError>> {
|
||||
FullstackContext::extract::<T, M>()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user