Routing not found route

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

You may need to add multiple decorators as shown here: Anvil routes redirect to a custom 404 page - #2 by stefano.menci

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