I can’t seem to get the Not Found Route to work. I get a No matching API endpoint
error page.
Here is a clone, clicking on the Missing Route button essentially manually navigates to a bad path.
Things I’ve looked at:
- Checked behavior for debug and published environments
- With logging enabled in
routing
and hitting a missing route, there is no debug information provided in the console unlike defined routes.
- The
_route.default_not_found_route_cls
is set correctly
_navigate.get_nav_location
provides a location object
_matcher.get_match
with a bad path returns None
- The
_matcher.get_not_found_match(location, default_not_found_route_cls)
returns a Match
instance with the default route as the route
param.
- Navigating to a missing route using
router.navigate('bad_path')
works as expected.
It is like the server side decides there is no matching route before routing
has a chance to handle it.
Any ideas on where I’m going wrong?
Here is a live version
Here is a clone
Under the hood the routing dependency converts each path from the Route subclasses to an anvil.server.route
And so if there is no registered route for a bad path then anvil will treat it as not having a matching end point.
When navigating on the client we can handle bad paths since we are not routing via the server.
A possible option might be to define a splat like route at the end of you routes. Something like:
class Splat(Route):
path = "/:x"
not_found_form = "Pages.NotFound"
def before_load(self, **loader_args):
raise NotFound
1 Like
Thanks @stucork. That makes sense, we have no option for an undefined route server side. Essentially we need Anvil to support definable 404 pages for apps for default_not_found
to work server side. Any idea how big of a deal that would be?
I guess we could create a generic route for a few navigation levels.
I’m not sure why this feels like a bad idea.
class Splat(Route):
path = "/:_"
not_found_form = "Pages.NotFound"
def before_load(self, **loader_kwargs):
raise NotFound
# Create generic Splats for a few navigation levels
for i in range(2, 5):
type(f"SplatLevel{i}", (Splat, ), {"path": i * Splat.path})
1 Like
I added multiple generic Routes but rather than using the server.route
decorator, I used this for loop to create new classes that inherit from my base Splat
class that increase the path level by i * "/:_"
:
for i in range(2, 5):
type(f"SplatLevel{i}", (Splat, ), {"path": i * Splat.path})
This is just a pretty uncommon way to use type()
.
2 Likes