Return a 404 when paring the route fails (#3860)
* return a 404 when paring the route fails * add a playwright test for fullstack routing status codes * Fix new playwright test * document SSRError * Make SSRError public and fix clippy * Move the error display bound to the routable trait * fix clippy * return a more generic 404 message * fix router tests
This commit is contained in:
1 parent
7b7357037f
commit
09a4b5eb4e
18 files changed
+253
-46
No files matched your search
@@ -1,7 +1,5 @@
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::{
|
||||
prelude::{provide_router_context, Outlet},
|
||||
routable::Routable,
|
||||
@@ -39,10 +37,7 @@ impl<R: Clone> PartialEq for RouterProps<R> {
|
||||
}
|
||||
|
||||
/// A component that renders the current route.
|
||||
pub fn Router<R: Routable + Clone>(props: RouterProps<R>) -> Element
|
||||
where
|
||||
<R as FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
pub fn Router<R: Routable + Clone>(props: RouterProps<R>) -> Element {
|
||||
use crate::prelude::{outlet::OutletContext, RouterContext};
|
||||
|
||||
use_hook(|| {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
error::Error,
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
@@ -11,6 +13,19 @@ use crate::{
|
||||
prelude::SiteMapSegment, routable::Routable, router_cfg::RouterConfig,
|
||||
};
|
||||
|
||||
/// An error that is thrown when the router fails to parse a route
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseRouteError {
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl Error for ParseRouteError {}
|
||||
impl Display for ParseRouteError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.message.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// This context is set in the root of the virtual dom if there is a router present.
|
||||
#[derive(Clone, Copy)]
|
||||
struct RootRouterContext(Signal<Option<RouterContext>>);
|
||||
@@ -94,10 +109,7 @@ pub struct RouterContext {
|
||||
}
|
||||
|
||||
impl RouterContext {
|
||||
pub(crate) fn new<R: Routable + 'static>(cfg: RouterConfig<R>) -> Self
|
||||
where
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
pub(crate) fn new<R: Routable + 'static>(cfg: RouterConfig<R>) -> Self {
|
||||
let subscribers = Arc::new(Mutex::new(HashSet::new()));
|
||||
let mapping = consume_child_route_mapping();
|
||||
|
||||
@@ -233,15 +245,21 @@ impl RouterContext {
|
||||
let absolute_route = self.full_route_string();
|
||||
// If this is a child route, map the absolute route to the child route before parsing
|
||||
let mapping = consume_child_route_mapping::<R>();
|
||||
match mapping.as_ref() {
|
||||
let route = match mapping.as_ref() {
|
||||
Some(mapping) => mapping
|
||||
.parse_route_from_root_route(&absolute_route)
|
||||
.unwrap_or_else(|| {
|
||||
panic!("route's display implementation must be parsable by FromStr")
|
||||
}),
|
||||
None => R::from_str(&absolute_route).unwrap_or_else(|_| {
|
||||
panic!("route's display implementation must be parsable by FromStr")
|
||||
}),
|
||||
.ok_or_else(|| "Failed to parse route".to_string()),
|
||||
None => {
|
||||
R::from_str(&absolute_route).map_err(|err| format!("Failed to parse route {err}"))
|
||||
}
|
||||
};
|
||||
|
||||
match route {
|
||||
Ok(route) => route,
|
||||
Err(err) => {
|
||||
throw_error(ParseRouteError { message: err });
|
||||
"/".parse().unwrap_or_else(|err| panic!("{err}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ mod contexts {
|
||||
pub(crate) mod router;
|
||||
pub use navigator::*;
|
||||
pub(crate) use router::*;
|
||||
pub use router::{root_router, GenericRouterContext, RouterContext};
|
||||
pub use router::{root_router, GenericRouterContext, ParseRouteError, RouterContext};
|
||||
}
|
||||
|
||||
mod router_cfg;
|
||||
|
||||
@@ -592,7 +592,7 @@ type SiteMapFlattened<'a> = FlatMap<
|
||||
note = "Routable should generally be derived using the `#[derive(Routable)]` macro."
|
||||
)
|
||||
)]
|
||||
pub trait Routable: FromStr + Display + Clone + 'static {
|
||||
pub trait Routable: FromStr<Err: Display> + Display + Clone + 'static {
|
||||
/// The error that can occur when parsing a route.
|
||||
const SITE_MAP: &'static [SiteMapSegment];
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ impl<R> Default for RouterConfig<R> {
|
||||
impl<R> RouterConfig<R>
|
||||
where
|
||||
R: Routable,
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
/// A function to be called whenever the routing is updated.
|
||||
///
|
||||
|
||||
Reference in new issue
Block a user