Skip to content

fix: make base URL for relative redirects consistent #9897

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

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

zqianem
Copy link

@zqianem zqianem commented May 10, 2023

Will fix #9880. Only commit for now is adding to the tests from #8842; does this look like the behavior we want?

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

@changeset-bot
Copy link

changeset-bot bot commented May 10, 2023

⚠️ No Changeset found

Latest commit: 9c8703c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@zqianem zqianem changed the title Make base URL for relative redirects consistent between server and client fix: make base URL for relative redirects consistent between server and client May 10, 2023
@zqianem zqianem changed the title fix: make base URL for relative redirects consistent between server and client fix: make base URL for relative redirects consistent May 10, 2023
@Rich-Harris
Copy link
Member

Ideally yeah, I think this would be the behaviour. I looked into the implementation though and I think it's going to be quite tricky — at present, the information for each 'node' of a route (which basically consists of the page options + the result of calling load) is bundled together, meaning we can't determine the correct trailingSlash value without also running the load function... which throws an error, preventing us from reading the value.

So we'd need to separate those two things in order to make it possible to normalize pathnames prior to redirection. If that causes client.js to increase in size then we'll have to consider how important we think it is to cover this edge case. Ideally, redirects should probably be root-relative so that this situation doesn't arise.

@zqianem
Copy link
Author

zqianem commented May 17, 2023

Here's a somewhat hacky implementation that covers the most common case when trailingSlashes isn't explicitly configured, as in the #9880 repro. It does run into the limitation where it can't read the config from files where the redirect is thrown, but ends up passing the tests because those throw the redirect in with-redirect/layout.js.

Should we also update the the docs to recommend absolute paths for redirects?

@zqianem zqianem marked this pull request as ready for review May 17, 2023 18:25
Comment on lines 1957 to 1971
/**
* @param {URL} url
* @param {Array<import('./types').BranchNode | undefined>} branch
*/
function normalize_url(url, branch) {
/** @type {import('types').TrailingSlash} */
let slash = 'never';
for (const node of branch) {
if (node?.slash !== undefined) slash = node.slash;
}
url.pathname = normalize_path(url.pathname, slash);
url.search = url.search; // turn `/?` into `/`
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we avoid mutating the URL here and instead return a new one? it's probably safe, but i've lost many hours of my life to these sorts of sneaky mutations in the past...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh strange, it looks like some existing behavior (test: Routing › redirects from /routing/? to /routing ) actually depends on the mutation happening. Will look into it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. I've reverted the commit that makes this function immutable in case anyone wants to use this branch for a temporary fix — will continue looking into getting a per-branch config without running the load function.

Comment on lines 710 to 716
// TODO get per-branch config without running load
// https://github.com/sveltejs/kit/pull/9897#issuecomment-1551723833
/** @type {Array<import('./types').BranchNode | undefined>} */
const temp_branch = (await Promise.allSettled(branch_promises)).map((s) =>
s.status === 'fulfilled' ? s.value : undefined
);
normalize_url(url, temp_branch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we really need to resolve the TODO before we can merge this :)

@dummdidumm
Copy link
Member

Just checking in - any updates on the issue? It sounds like the fix is quite complicated and the PR is not ready yet.

@zqianem
Copy link
Author

zqianem commented Jul 4, 2023

Thank you for the reminder.

I have been rather stumped by this — managed to get it working for .js but not for .server.js routes; I'll push those commits now. I'd be okay with it if anyone else wants to pick up this PR from here.

Some miscellaneous notes:

  • setting server.hmr.overlay to false resolves the flakiness in /test/apps/basics/
  • current behavior before this PR depends on get_navigation_result_from_branch mutating its url argument
  • function call graph for src/runtime/client/client.js is a bit complex:
    image

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

Successfully merging this pull request may close these issues.

Client router doesn't strip trailing slashes before redirecting
4 participants