-
-
Notifications
You must be signed in to change notification settings - Fork 10.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: support basename and relative routing in loader/action redirects #9447
Conversation
Co-authored-by: Mikaël ANZANO <[email protected]>
🦋 Changeset detectedLatest commit: d00e5bc The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
"@remix-run/router": patch | ||
--- | ||
|
||
Support basename and relative routing in loader/action redirects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did this as a patch/bug fix (as opposed to a minor/new feature) since redirects probably should have supported basename
and relative routing from the get go. This would be new behavior for remix though when we bring it over - but I would argue non-breaking
type FetchLoadMatch = [ | ||
string, | ||
AgnosticDataRouteMatch, | ||
AgnosticDataRouteMatch[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now track both the single fetcher match and it's hierarchical matched on fetcher.load
so that we can do proper relative routing on fetcher revalidation redirects.
matches, | ||
router.basename |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now expect the hierarchy of matches and the basename for all calls to callLoaderOrAction
, that way we can make changes to the Response
Location
header as needed.
// Support relative routing in redirects | ||
let activeMatches = matches.slice(0, matches.indexOf(match) + 1); | ||
let routePathnames = getPathContributingMatches(activeMatches).map( | ||
(match) => match.pathnameBase | ||
); | ||
let requestPath = createURL(request.url).pathname; | ||
location = resolveTo(location, routePathnames, requestPath).pathname; | ||
invariant( | ||
location, | ||
`Unable to resolve redirect location: ${result.headers.get("Location")}` | ||
); | ||
|
||
// Prepend the basename to the redirect location if we have one | ||
if (basename) { | ||
let path = createURL(location).pathname; | ||
location = path === "/" ? basename : joinPaths([basename, path]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the redirect location
to account for basename and relative routing.
// redirect. We also update the Location header in place in this flow so | ||
// basename and relative routing is taken into account | ||
if (isStaticRequest) { | ||
result.headers.set("Location", location); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this was a static request, we also need to replace the Response
Location
header with the updated value before throwing it back to our server.
packages/router/utils.ts
Outdated
(!match.route.index && | ||
match.pathnameBase !== matches[index - 1].pathnameBase) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brought over from react-router
so relative routing ignores index and pathless layout routes. IF we don't want this duped, I can export this as an undocumented API from @remix-run/router
and import it into react-router
packages/router/router.ts
Outdated
navigation.location.pathname === "/" | ||
? basename | ||
: joinPaths([basename, navigation.location.pathname]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ended up removing this original approach in startRedirectNavigation
since it doesn't work for static requests where we return the Response
itself. Moved the primary logic down into callLoaderOrAction
LGTM 👍 |
Hi, it seems like useFetcher load method still does not respect basename. |
@cantti Can you open a new issue for that? 🙏🏼 |
@machour sure, done. |
Builds on top of original PR (#9418) to handle
basename
in loader/action redirects and also adds support for relative routing in redirects.Basename example:
Relative routing example:
Closes #9417
Co-authored-by: Mikaël ANZANO [email protected]