Skip to content
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

Merged
merged 9 commits into from
Oct 21, 2022

Conversation

brophdawg11
Copy link
Contributor

@brophdawg11 brophdawg11 commented Oct 11, 2022

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:

let router = createBrowserRouter([{
  path: '/',
  loader() {
    // This will now properly redirect the browser to /base/other
    return redirect('/other');
  },
}], { basename: '/base'}

Relative routing example:

let router = createBrowserRouter([{
  path: '/',
  children: [{
    path: 'parent',
    children: [{
      path: 'child',
      loader() {
        // This will now properly redirect the browser to /parent
        return redirect('..');
      },
    }],
  }]
}]);

Closes #9417

Co-authored-by: Mikaël ANZANO [email protected]

@changeset-bot
Copy link

changeset-bot bot commented Oct 11, 2022

🦋 Changeset detected

Latest commit: d00e5bc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@remix-run/router Patch
react-router Patch
react-router-dom Patch
react-router-dom-v5-compat Patch
react-router-native Patch

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

@brophdawg11 brophdawg11 linked an issue Oct 12, 2022 that may be closed by this pull request
"@remix-run/router": patch
---

Support basename and relative routing in loader/action redirects
Copy link
Contributor Author

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[]
Copy link
Contributor Author

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.

Comment on lines +960 to +961
matches,
router.basename
Copy link
Contributor Author

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.

Comment on lines +2463 to +2479
// 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]);
}
Copy link
Contributor Author

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);
Copy link
Contributor Author

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.

(!match.route.index &&
match.pathnameBase !== matches[index - 1].pathnameBase)
);
}
Copy link
Contributor Author

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

navigation.location.pathname === "/"
? basename
: joinPaths([basename, navigation.location.pathname]);
}
Copy link
Contributor Author

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

@brophdawg11 brophdawg11 changed the title fix: respect basename in loaders and actions redirects fix: support basename and relative routing in loader/action redirects Oct 12, 2022
@mjackson
Copy link
Member

LGTM 👍

@cantti
Copy link

cantti commented Dec 8, 2022

Hi, it seems like useFetcher load method still does not respect basename.

@machour
Copy link
Contributor

machour commented Dec 8, 2022

@cantti Can you open a new issue for that? 🙏🏼

@cantti
Copy link

cantti commented Dec 9, 2022

@machour sure, done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Basename is not respected in loaders and actions redirects
5 participants