redirects, middleware, Transport, set/capture error status (#4751)

* wip: redirect

* redirect example

* fix file upload not in a form

* wip

* deny missing cfgs

* wip: add router fallback but it's not working

* fix suspense bug after rebuilds that queued work

* more cleanup

* add test for error codes

* add helpful comment

* bring back middleware annotation

* fix cfg

* add server feature

* fix doctest

* just disable liveview test for now

* fix liveview

* dont send init

* cache more playwright!

* add more pkgs to cache
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-10-10 21:43:57 -07:00
1 parent 8a81475ba8
commit 9243ef4128
35 files changed
+935 -800

No files matched your search

+1
View File
@@ -52,6 +52,7 @@ mod client;
pub use client::*;
pub use axum::extract::Json;
pub use axum::response::{NoContent, Redirect};
pub use payloads::*;
pub mod payloads {
+35 -1
View File
@@ -1,9 +1,10 @@
use super::*;
use crate::{ClientResponse, FromResponse};
pub use axum::extract::Json;
use axum::response::Html;
use axum::response::{Html, NoContent, Redirect};
use dioxus_fullstack_core::{RequestError, ServerFnError};
use futures::StreamExt;
use http::StatusCode;
use std::future::Future;
impl<T: From<String>> FromResponse for Html<T> {
@@ -33,6 +34,39 @@ impl<T: DeserializeOwned> FromResponse for Json<T> {
}
}
impl FromResponse for Redirect {
fn from_response(res: ClientResponse) -> impl Future<Output = Result<Self, ServerFnError>> {
async move {
let location = res
.headers()
.get(http::header::LOCATION)
.ok_or_else(|| RequestError::Redirect("Missing Location header".into()))?
.to_str()
.map_err(|_| RequestError::Redirect("Invalid Location header".into()))?;
match res.status() {
StatusCode::SEE_OTHER => Ok(Redirect::to(location)),
StatusCode::TEMPORARY_REDIRECT => Ok(Redirect::temporary(location)),
StatusCode::PERMANENT_REDIRECT => Ok(Redirect::permanent(location)),
_ => Err(RequestError::Redirect("Not a redirect status code".into()).into()),
}
}
}
}
impl FromResponse for NoContent {
fn from_response(res: ClientResponse) -> impl Future<Output = Result<Self, ServerFnError>> {
async move {
let status = res.status();
if status == StatusCode::NO_CONTENT {
Ok(NoContent)
} else {
let body = res.text().await.unwrap_or_else(|_| "".into());
Err(RequestError::Status(body, status.into()).into())
}
}
}
}
/// Implementation of `FromResponse` for `axum::response::Response`.
///
/// This allows converting a `ClientResponse` (from a client-side HTTP request)