Skip to content

router.resolve did not handle <base> correctly #3819

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

Closed
ichaoX opened this issue Dec 30, 2022 · 2 comments
Closed

router.resolve did not handle <base> correctly #3819

ichaoX opened this issue Dec 30, 2022 · 2 comments

Comments

@ichaoX
Copy link

ichaoX commented Dec 30, 2022

Version

3.6.5

Reproduction link

5s3iuf.csb.app/root/main.html

Steps to reproduce

Click on Link A or open Link B in a new tab.

And check the generated href attribute in the inspector.

What is expected?

In hash mode, the following results are logical, I would prefer the last one, because the HashHistory is not related to the baseURI and the availability of the <base> source is unknown.

// "https://example.com/root/rel/path#/bar"
new URL("#/bar",document.baseURI).href

// "https://example.com/root/main.html#/bar"
new URL("#/bar",location).href
// If location.href and document.baseURI are same-origin or both paths are the same, 
// it is possible to slice the generated URL to shorten it.

What is actually happening?

The generated href attributes are all "/./rel/path#/foo/#/bar".

Both the relative path and the hash of Link A are not handled correctly.

Link B has the same issue when opened in a new tab.

@posva
Copy link
Member

posva commented Jan 3, 2023

A base should likely not include a hash in it. Note that it changes the browser behavior of <a> and other things (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base). For instance, when you are opening in a new tab, that's the browser, vue-router simply lets that event happen

@posva posva closed this as completed Jan 3, 2023
@ichaoX
Copy link
Author

ichaoX commented Jan 3, 2023

A base should likely not include a hash in it. [citation needed]

I have tested document.baseURI and it will contain the hash value.

Another main problem is that router.resolve treats it as an absolute path, while <base> is a relative path.

It's less reliable here:

function normalizeBase (base: ?string): string {
if (!base) {
if (inBrowser) {
// respect <base> tag
const baseEl = document.querySelector('base')
base = (baseEl && baseEl.getAttribute('href')) || '/'
// strip full URL origin
base = base.replace(/^https?:\/\/[^\/]+/, '')
} else {
base = '/'
}
}
// make sure there's the starting slash
if (base.charAt(0) !== '/') {
base = '/' + base
}
// remove trailing slash
return base.replace(/\/$/, '')
}

The hash mode should not join the '/' in the middle, the server may return 404 Not Found.

vue-router/src/router.js

Lines 280 to 283 in 492bf0e

function createHref (base: string, fullPath: string, mode) {
var path = mode === 'hash' ? '#' + fullPath : fullPath
return base ? cleanPath(base + '/' + path) : path
}

To solve the problem of inconsistent opening in new tabs in hash mode, it can either do nothing special for <base>, or use new URL("#/bar",location).href to generate the URL.

ichaoX added a commit to ichaoX/vue-router that referenced this issue Jan 11, 2023
* Resolve the href in `<base>` correctly.

* In hash mode, the hash in base is automatically removed and the base trailing slash is distinguished.

* By default the result of `router.resolve().href` is the same as the actual switched URL.
ichaoX added a commit to ichaoX/vue-router that referenced this issue May 24, 2023
* Resolve the href in `<base>` correctly.

* In hash mode, the hash in base is automatically removed and the base trailing slash is distinguished.

* By default the result of `router.resolve().href` is the same as the actual switched URL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants