-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
Properly encode/decode the percentage character (% -> %25) across browsers and upon initial navigation #2725
Comments
In most cases, we can avoid using special characters in development. But if we got decode error, I think we should catch it manually and try to find the closest asterisk match. |
I recommend adding the following testcases, which seem to be extra nasty:
Also, this should be tested with server-side-rendering. It looks like this whole thing only works if the |
Not sure, if this is the same issue, but initial navigation for routes with percent-encoded characters does not work. The problem was initially reported in nextcloud/tasks#479. Have a look at this example: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-router"></script>
<div id="app">
<router-link
v-for="item in items"
:to="{name: 'items', params: {itemId: item.id }}"
:key="item.id"
>
Go to {{ item.name }}
</router-link>
<router-view></router-view>
</div>
<script>
const items = [
{
id: 'item1',
name: 'Item1',
},
{
id: 'item2_with_ö',
name: 'Item2',
},
{
id: 'item3_with_escaped_%C3%B6',
name: 'Item3',
},
]
const ItemsComponent = Vue.component('Items', {
name: 'Items',
props: {
itemId: {
type: String
}
},
computed: {
item: function() {
return items.find(item => item.id === this.itemId)
},
},
template: `
<div v-if="item">
<span>{{ item.id }}</span>
<span>{{ item.name }}</span>
</div>
<div v-else>
<span>Item not found</span>
<span>ItemId: {{ itemId }}</span>
</div>
`
})
const routes = [
{ name: 'items',
path: '/items/:itemId',
component: ItemsComponent,
props: true,
},
]
const router = new VueRouter({
routes
})
const app = new Vue({
router,
data() {
return {
items: items,
}
}
}).$mount('#app')
</script>
</body>
</html> Clicking the links works fine, the correct item is loaded and the route-view shows the correct item. But if you reload the page after clicking on I would appreciate some feedback if this is the same issue described here or not. Thanks a lot! |
onDecode: (req) => {
let url = req.url
try {
url = decodeURI(req.url)
}
catch (error) {
// Rethrow error
if (error.message !== 'URI malformed') {
throw error
}
url = decodeURI(unescape(req.url))
// Fix url also on Nuxt side
req.url = url
}
return url
} I had issues with ISO urls and fixed it like that. |
@alanaasmaa May I ask where to put / how to use |
@raimund-schluessler You have to use a version that is not yet released. Then in nuxt config redirect: {
rules: [
{ from: /^\/page(?:\/?)(?:\?(.*))?$/, to: '/?$1' },
],
onDecode: (req) => {
let url = req.url
try {
url = decodeURI(req.url)
}
catch (error) {
// Rethrow error
if (error.message !== 'URI malformed') {
throw error
}
url = decodeURI(unescape(req.url))
// Fix url also on Nuxt side
req.url = url
}
return url
},
onDecodeError: (error, req, res, next) => next(error) I also had to nuke node_modules |
A simple example with steps to reproduce:
<html>
<meta charset="UTF-8">
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
</div>
<script>
let homeComponent = Vue.component('homePage', {
template: `
<router-link :to="{ name: 'tag', params: { tag: testTag } }" tag="button">
Go to "{{testTag}}"
</router-link>
`,
data () {
return {
testTag: 'this-is-a-test-tag-%'
}
},
})
let tagComponent = Vue.component('tagPage', {
template: `
<div>
<p>
this is the page for tag <b>"{{$route.params.tag}}"</b></br></br>
refresh now to induce the bug.
</p>
<router-link :to="{ name: 'home' }" tag="button">Go back</router-link>
</div>
`
})
let app = new Vue({
el: '#app',
template: `
<router-view></router-view>
`,
router: new VueRouter({
routes: [
{
path: '/',
name: 'home',
component: homeComponent
},
{
path: '/tag/:tag',
name: 'tag',
component: tagComponent
}
]
})
})
</script>
</body>
</html> |
Fix an issue where page browsing to a route and then reloading leads to inconsistent parameters and fullPath values.
Fix an issue where page browsing to a route and then reloading leads to inconsistent parameters and fullPath values.
I open a PR for this issue, can you review please ? #3213 |
I've seen the issue has been fixed on 4.x. It is expected to be fixed on the current release 3.3.X? If not, is there a release date for v4.x (I could not manage to find it)? I have some projects which I have to deliver soon, and I would apreciate the information in order to wait for the fix, or trying to remove the percentatge from the path params; which will cause me many troubles :). Thank you very much |
v4 is for Vue 3, it already exist under the |
Currently, the percentage character creates multiple issues and inconsistencies. This is partly due to:
%
is forbidden as part of the pathname in the URL per its spec (https://url.spec.whatwg.org/#path-state) if not escapedIn Vue router, we have multiple inconsistencies between asterisk path, param paths and regular path regarding escaping these characters and whether the navigation is initial or triggered by a push/router-link
Given this set of routes in history mode
History mode / Chrome, IE 11,10
to
$router
info after clicking$router
info on direct navigation/%7D
*
/%7D
/%7D
-/}
/}
-/}
/}
as the link instead/}
*
/%7D
/}
-/}
/%7D
)/%25
*
/%25
/%25
-/%
/%
to be consistent?/%
*
/foo/%7D
/foo/:p
/%7D
/%7D
- p =}
/}
- p =}
/foo/}
/foo/}
/foo/:p
/%7D
/}
- p =}
/}
- p =}
/foo/%25
/foo/:p
/%25
/%25
- p =%
Hash mode / TODO
Query / TODO
Complete html file to test. Requires a
vue-router.js
file in the same folderindex.html
The text was updated successfully, but these errors were encountered: