diff --git a/examples/basic/app.js b/examples/basic/app.js
index b248d7841..ab33dd9c2 100644
--- a/examples/basic/app.js
+++ b/examples/basic/app.js
@@ -45,7 +45,7 @@ const router = new VueRouter({
{ path: '/', component: Home },
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
- { path: '/é', component: Unicode },
+ { path: encodeURI('/é'), component: Unicode },
{ path: '/query/:q', component: Query }
]
})
@@ -76,9 +76,9 @@ const vueInstance = new Vue({
/bar
-
/é
- /é?t=%ñ
- /é#%25ñ
+ /é
+ /é?t=%ñ
+ /é#%25ñ
{{ props.route.path }} (with v-slot).
diff --git a/examples/hash-mode/app.js b/examples/hash-mode/app.js
index ee58238e9..16475ffc8 100644
--- a/examples/hash-mode/app.js
+++ b/examples/hash-mode/app.js
@@ -45,8 +45,8 @@ const router = new VueRouter({
{ path: '/', component: Home }, // all paths are defined without the hash.
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar },
- { path: '/é', component: Unicode },
- { path: '/é/:unicode', component: Unicode },
+ { path: encodeURI('/é'), component: Unicode },
+ { path: encodeURI('/é/:unicode'), component: Unicode },
{ path: '/query/:q', component: Query, name: 'param' }
]
})
@@ -64,10 +64,10 @@ const vueInstance = new Vue({
/foo
/bar
/bar
- /é
- /é/ñ
- /é/ñ?t=%ñ
- /é/ñ#é
+ /é
+ /é/ñ
+ /é/ñ?t=%ñ
+ /é/ñ#é
/query/A%
/query/A% (object)
/query/A%2FE
diff --git a/src/create-matcher.js b/src/create-matcher.js
index 3392b2c07..fcb8a8092 100644
--- a/src/create-matcher.js
+++ b/src/create-matcher.js
@@ -7,6 +7,7 @@ import { createRoute } from './util/route'
import { fillParams } from './util/params'
import { createRouteMap } from './create-route-map'
import { normalizeLocation } from './util/location'
+import { decode } from './util/query'
export type Matcher = {
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
@@ -175,14 +176,6 @@ function matchRoute (
path: string,
params: Object
): boolean {
- try {
- path = decodeURI(path)
- } catch (err) {
- if (process.env.NODE_ENV !== 'production') {
- warn(false, `Error decoding "${path}". Leaving it intact.`)
- }
- }
-
const m = path.match(regex)
if (!m) {
@@ -195,7 +188,7 @@ function matchRoute (
const key = regex.keys[i - 1]
if (key) {
// Fix #1994: using * with props: true generates a param named 0
- params[key.name || 'pathMatch'] = m[i]
+ params[key.name || 'pathMatch'] = typeof m[i] === 'string' ? decode(m[i]) : m[i]
}
}
diff --git a/src/create-route-map.js b/src/create-route-map.js
index c05896845..01c0836d2 100644
--- a/src/create-route-map.js
+++ b/src/create-route-map.js
@@ -70,6 +70,14 @@ function addRouteRecord (
path || name
)} cannot be a ` + `string id. Use an actual component instead.`
)
+
+ warn(
+ // eslint-disable-next-line no-control-regex
+ !/[^\u0000-\u007F]+/.test(path),
+ `Route with path "${path}" contains unencoded characters, make sure ` +
+ `your path is correctly encoded before passing it to the router. Use ` +
+ `encodeURI to encode static segments of your path.`
+ )
}
const pathToRegexpOptions: PathToRegexpOptions =
diff --git a/test/unit/specs/create-map.spec.js b/test/unit/specs/create-map.spec.js
index 25bdb3d45..57c81afe1 100644
--- a/test/unit/specs/create-map.spec.js
+++ b/test/unit/specs/create-map.spec.js
@@ -81,6 +81,15 @@ describe('Creating Route Map', function () {
)
})
+ it('warns about unencoded entities', function () {
+ process.env.NODE_ENV = 'development'
+ maps = createRouteMap([{ path: '/é', component: Home }])
+ expect(console.warn).toHaveBeenCalledTimes(1)
+ expect(console.warn.calls.argsFor(0)[0]).toMatch(
+ 'vue-router] Route with path "/é"'
+ )
+ })
+
it('in development, throws if path is missing', function () {
process.env.NODE_ENV = 'development'
expect(() => {