More fullstack fixes (#4737)
* allow `--server` only builds! * rollback example * capture `/:route` routes * fix: properly implement file uploads in forms * implement desktop form uploads * Performant serialization of form bytes * finish up file stuff * cleanups * add request headers to streaming context * remove some unwraps
This commit is contained in:
1 parent
fc01a002fd
commit
92792aded9
47 files changed
+1241
-703
No files matched your search
@@ -1,5 +1,9 @@
|
||||
use crate::ServerFnError;
|
||||
use axum_core::{extract::FromRequest, response::IntoResponse};
|
||||
use dioxus_core::try_consume_context;
|
||||
use dioxus_signals::{ReadableExt, Signal, WritableExt};
|
||||
use http::request::Parts;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
/// The status of the streaming response
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
@@ -13,23 +17,26 @@ pub enum StreamingStatus {
|
||||
}
|
||||
|
||||
/// The context dioxus fullstack provides for the status of streaming responses on the server
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StreamingContext {
|
||||
current_status: Signal<StreamingStatus>,
|
||||
request_headers: Rc<RefCell<http::request::Parts>>,
|
||||
}
|
||||
|
||||
impl Default for StreamingContext {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
impl PartialEq for StreamingContext {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.current_status == other.current_status
|
||||
&& Rc::ptr_eq(&self.request_headers, &other.request_headers)
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamingContext {
|
||||
/// Create a new streaming context. You should not need to call this directly. Dioxus fullstack will
|
||||
/// provide this context for you.
|
||||
pub fn new() -> Self {
|
||||
pub fn new(parts: Parts) -> Self {
|
||||
Self {
|
||||
current_status: Signal::new(StreamingStatus::RenderingInitialChunk),
|
||||
request_headers: Rc::new(RefCell::new(parts)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +55,42 @@ impl StreamingContext {
|
||||
pub fn current_status(&self) -> StreamingStatus {
|
||||
*self.current_status.read()
|
||||
}
|
||||
|
||||
/// Access the http request parts mutably. This will allow you to modify headers and other parts of the request.
|
||||
pub fn parts_mut(&self) -> std::cell::RefMut<'_, http::request::Parts> {
|
||||
self.request_headers.borrow_mut()
|
||||
}
|
||||
|
||||
/// Extract an axum extractor from the current request. This will always use an empty body for the request,
|
||||
/// since it's assumed that rendering the app is done under a `GET` request.
|
||||
pub async fn extract<T: FromRequest<(), M>, M>() -> Result<T, ServerFnError> {
|
||||
let this = Self::current()
|
||||
.ok_or_else(|| ServerFnError::new("No StreamingContext found".to_string()))?;
|
||||
|
||||
let parts = this.request_headers.borrow_mut().clone();
|
||||
let request =
|
||||
axum_core::extract::Request::from_parts(parts, axum_core::body::Body::empty());
|
||||
match T::from_request(request, &()).await {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => {
|
||||
let resp = err.into_response();
|
||||
Err(ServerFnError::from_axum_response(resp).await)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current `StreamingContext` if it exists. This will return `None` if called on the client
|
||||
/// or outside of a streaming response on the server.
|
||||
pub fn current() -> Option<Self> {
|
||||
if let Some(rt) = dioxus_core::Runtime::try_current() {
|
||||
let id = rt.try_current_scope_id()?;
|
||||
if let Some(ctx) = rt.consume_context::<StreamingContext>(id) {
|
||||
return Some(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Commit the initial chunk of the response. This will be called automatically if you are using the
|
||||
|
||||
Reference in new issue
Block a user