Client navigations and server middleware (the navigation check)
A client navigation into a route whose subtree runs server middleware asks the server first: the browser posts { "path": "/app/path", "search": "?x=1" } to POST…
A client navigation into a route whose subtree runs server middleware asks the server first: the browser posts
{ "path": "/app/path", "search": "?x=1" } to POST {base}/_dusk/nav with the header x-dusk-navigation: check. The
middleware of the target runs with:
event.urlequal to the TARGET (path and search), not the/_dusk/navrequest;event.isNavigationChecktrue (false for every document request).
A middleware can therefore redirect a blocked navigation the way it redirects a document request:
ts
if (event.isNavigationCheck || !isSignedIn(event)) {
throw redirect(`/sign-in?redirect_url=${encodeURIComponent(`${event.url.pathname}${event.url.search}`)}`);
}
The client applies the answer with the same meaning as a document redirect:
- a redirect inside the app is a router navigation that replaces the history entry of the blocked URL;
- a redirect to another origin leaves the app (
location.replace), and the navigation stays pending until the page leaves, so no error boundary flashes; - a refusal without a redirect shows the status in the route's error boundary, as a loader error does.
A search that is not a query (no leading ?, a fragment, a backslash, control characters) is a 400.