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

分类和标签包含中文会导致路由匹配不到,跳转至404页面 #276

Closed
1 task done
ATQQ opened this issue Nov 21, 2020 · 14 comments
Closed
1 task done
Labels
good first issue Good for newcomers

Comments

@ATQQ
Copy link
Contributor

ATQQ commented Nov 21, 2020

  • I confirm that this is an issue rather than a question.

Bug report

What is actually happening?

在文章中,标签和分类如果包含中文,会在页面访问指定路由时404

---
title: api
date: 2020-05-29
categories: 
 - 中文分类
tags: 
 - 中文标签
---

复现步骤

  1. 脚手架创建项目,随意修改一个文章的分类/标签 包含中文

图片

  1. 运行后控制台会有警告

图片

提示路由的路径包含不可编码的字符

试验了一下 Vue-router是支持中文路由的

  1. 访问效果通过按钮目录点击导航没问题,但如果直接输入目标地址就是404

点它 ok
图片

直接访问它对应的路由,不ok

https://sugarat.top/categories/%E5%85%B6%E5%AE%83/

Other relevant information

  • Your OS: 应该也不是操作系统问题
    • Mac OS BigSur
    • Linux
  • Node.js version: 都切换了应该不是 Node的问题
    • 10
    • 12
    • 14
  • VuePress version: 都试了也不行
    • 1.5.1
    • 1.71
  • VuePress-theme-reco version: 怀疑是这个问题
    • 1.5.7
  • Which package manager did you use for the install(npm/cnpm/yarn)?
    • npm
    • yarn
@ATQQ
Copy link
Contributor Author

ATQQ commented Nov 22, 2020

问题的原因

浏览器对直接输入的中文url做了一次encode导致 匹配不到对应的path,然后就打到了404的路由

多年前有人在vue-router提过此问题 vuejs/vue-router#838

在vue脚手架中使用中文路径是OK的不会触发warn,猜测是在哪执行了encode,待debug看执行路径

这个bug应该是在vuepress,在vuepress中出现中文路径的文件夹就会抛出上述的 warn

目前的解决方案

修改vue-router 的部分源码

node_modules/vue-router/dist/vue-router.esm.js

在match方法中加入以下语句,即可

function match (
    raw,
    currentRoute,
    redirectedFrom
  ) {

  if(typeof raw ==='string'){
     raw = decode(raw)
  }
  // ...code
}

图片

@Mu-Yan
Copy link

Mu-Yan commented Nov 25, 2020

问题的原因

浏览器对直接输入的中文url准备一次编码导致匹配不到对应的路径,然后就打到了404的路由

多年前有人在vue-router提过此问题vuejs / vue-router#838

在vue脚手架中使用中文路径是OK的不会触发warn,猜测是在哪执行了编码,待调试看执行路径

这个bug应该是在vuepress,在vuepress中出现中文路径的文件夹就会抛出上述的warn

目前的解决方案

修改vue-router的部分源码

node_modules / vue-router / dist / vue-router.esm.js

在match方法中加入以下语句,即可

函数 匹配 
    raw 
    currentRoute 
    redirectedFrom 
   { 

  if (typeof  raw  === 'string' { 
     raw  = 解码(raw 
  } 
  // ...代码
}

图片

直接修改vue-router源码无法治本,如果重新 npm install 就需要再次更改源码

可以通过 将主题更换至本地,而后修改 vuepress-theme-reco 本地主题的 enhanceApp.js 对应源码解决该问题,这样只要不更新主题就可一次解决

image

// enhanceApp.js
import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import { addLinkToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss } from '@theme/helpers/other'

import Router from 'vue-router'

const router = new Router({
  mode: 'history'
})

// 防止相同路由跳转时报错
const VueRouterPush = Router.prototype.push
Router.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}

export default ({
  Vue,
  siteData,
  isServer,
  router
}) => {
  Vue.mixin(postMixin)
  Vue.mixin(localMixin)
  if (!isServer) {
    addLinkToHead('//at.alicdn.com/t/font_1030519_2ciwdtb4x65.css')
    registerCodeThemeCss(siteData.themeConfig.codeTheme)
  }

  router.beforeEach((to, from, next) => {
    // 解决非ASCII文件名的路由, 防止 404
    const decodedPath = decodeURIComponent(to.path)
    if (decodedPath !== to.path) {
      next(Object.assign({}, to, {
        fullPath: decodeURIComponent(to.fullPath),
        path: decodedPath
      }))
    } else {
      next()
    }
  })
}

@ATQQ
Copy link
Contributor Author

ATQQ commented Nov 25, 2020

问题的原因

浏览器对直接输入的中文url准备一次编码导致匹配不到对应的路径,然后就打到了404的路由
多年前有人在vue-router提过此问题vuejs / vue-router#838
在vue脚手架中使用中文路径是OK的不会触发warn,猜测是在哪执行了编码,待调试看执行路径
这个bug应该是在vuepress,在vuepress中出现中文路径的文件夹就会抛出上述的warn

目前的解决方案

修改vue-router的部分源码
node_modules / vue-router / dist / vue-router.esm.js
在match方法中加入以下语句,即可

函数 匹配 
    raw 
    currentRoute 
    redirectedFrom 
   { 

  if (typeof  raw  === 'string' { 
     raw  = 解码(raw 
  } 
  // ...代码
}

图片

直接修改vue-router源码无法治本,如果重新 npm install 就需要再次更改源码

可以通过 将主题更换至本地,而后修改 vuepress-theme-reco 本地主题的 enhanceApp.js 对应源码解决该问题,这样只要不更新主题就可一次解决

image

// enhanceApp.js
import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import { addLinkToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss } from '@theme/helpers/other'

import Router from 'vue-router'

const router = new Router({
  mode: 'history'
})

// 防止相同路由跳转时报错
const VueRouterPush = Router.prototype.push
Router.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}

export default ({
  Vue,
  siteData,
  isServer,
  router
}) => {
  Vue.mixin(postMixin)
  Vue.mixin(localMixin)
  if (!isServer) {
    addLinkToHead('//at.alicdn.com/t/font_1030519_2ciwdtb4x65.css')
    registerCodeThemeCss(siteData.themeConfig.codeTheme)
  }

  router.beforeEach((to, from, next) => {
    // 解决非ASCII文件名的路由, 防止 404
    const decodedPath = decodeURIComponent(to.path)
    if (decodedPath !== to.path) {
      next(Object.assign({}, to, {
        fullPath: decodeURIComponent(to.fullPath),
        path: decodedPath
      }))
    } else {
      next()
    }
  })
}

多谢嘞👍

@ATQQ
Copy link
Contributor Author

ATQQ commented Nov 25, 2020

问题的原因

浏览器对直接输入的中文url准备一次编码导致匹配不到对应的路径,然后就打到了404的路由
多年前有人在vue-router提过此问题vuejs / vue-router#838
在vue脚手架中使用中文路径是OK的不会触发warn,猜测是在哪执行了编码,待调试看执行路径
这个bug应该是在vuepress,在vuepress中出现中文路径的文件夹就会抛出上述的warn

目前的解决方案

修改vue-router的部分源码
node_modules / vue-router / dist / vue-router.esm.js
在match方法中加入以下语句,即可

函数 匹配 
    raw 
    currentRoute 
    redirectedFrom 
   { 

  if (typeof  raw  === 'string' { 
     raw  = 解码(raw 
  } 
  // ...代码
}

图片

直接修改vue-router源码无法治本,如果重新 npm install 就需要再次更改源码
可以通过 将主题更换至本地,而后修改 vuepress-theme-reco 本地主题的 enhanceApp.js 对应源码解决该问题,这样只要不更新主题就可一次解决
image

// enhanceApp.js
import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import { addLinkToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss } from '@theme/helpers/other'

import Router from 'vue-router'

const router = new Router({
  mode: 'history'
})

// 防止相同路由跳转时报错
const VueRouterPush = Router.prototype.push
Router.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}

export default ({
  Vue,
  siteData,
  isServer,
  router
}) => {
  Vue.mixin(postMixin)
  Vue.mixin(localMixin)
  if (!isServer) {
    addLinkToHead('//at.alicdn.com/t/font_1030519_2ciwdtb4x65.css')
    registerCodeThemeCss(siteData.themeConfig.codeTheme)
  }

  router.beforeEach((to, from, next) => {
    // 解决非ASCII文件名的路由, 防止 404
    const decodedPath = decodeURIComponent(to.path)
    if (decodedPath !== to.path) {
      next(Object.assign({}, to, {
        fullPath: decodeURIComponent(to.fullPath),
        path: decodedPath
      }))
    } else {
      next()
    }
  })
}

多谢嘞👍

问题的原因

浏览器对直接输入的中文url准备一次编码导致匹配不到对应的路径,然后就打到了404的路由
多年前有人在vue-router提过此问题vuejs / vue-router#838
在vue脚手架中使用中文路径是OK的不会触发warn,猜测是在哪执行了编码,待调试看执行路径
这个bug应该是在vuepress,在vuepress中出现中文路径的文件夹就会抛出上述的warn

目前的解决方案

修改vue-router的部分源码
node_modules / vue-router / dist / vue-router.esm.js
在match方法中加入以下语句,即可

函数 匹配 
    raw 
    currentRoute 
    redirectedFrom 
   { 

  if (typeof  raw  === 'string' { 
     raw  = 解码(raw 
  } 
  // ...代码
}

图片

直接修改vue-router源码无法治本,如果重新 npm install 就需要再次更改源码

可以通过 将主题更换至本地,而后修改 vuepress-theme-reco 本地主题的 enhanceApp.js 对应源码解决该问题,这样只要不更新主题就可一次解决

image

// enhanceApp.js
import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import { addLinkToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss } from '@theme/helpers/other'

import Router from 'vue-router'

const router = new Router({
  mode: 'history'
})

// 防止相同路由跳转时报错
const VueRouterPush = Router.prototype.push
Router.prototype.push = function push (to) {
  return VueRouterPush.call(this, to).catch(err => err)
}

export default ({
  Vue,
  siteData,
  isServer,
  router
}) => {
  Vue.mixin(postMixin)
  Vue.mixin(localMixin)
  if (!isServer) {
    addLinkToHead('//at.alicdn.com/t/font_1030519_2ciwdtb4x65.css')
    registerCodeThemeCss(siteData.themeConfig.codeTheme)
  }

  router.beforeEach((to, from, next) => {
    // 解决非ASCII文件名的路由, 防止 404
    const decodedPath = decodeURIComponent(to.path)
    if (decodedPath !== to.path) {
      next(Object.assign({}, to, {
        fullPath: decodeURIComponent(to.fullPath),
        path: decodedPath
      }))
    } else {
      next()
    }
  })
}

这个直接安排个PR给主题吧哈哈

@Mu-Yan
Copy link

Mu-Yan commented Nov 25, 2020

这只是我目前使用一种解决方法,毕竟遇到了这个问题。
我看案例展示的基本没这个问题,不知道是不是都自定义了一波,还是配置不一致原因。

@Mu-Yan
Copy link

Mu-Yan commented Nov 25, 2020

@recoluan 有空的话,麻烦看下这个问题是否是个例问题

@ATQQ
Copy link
Contributor Author

ATQQ commented Nov 25, 2020

我猜应该不是个例问题,我拿reco主题(1.5.7)的cli创建的模板项目,在不同操作系统都有这个问题

主要就是路由中匹配不到 encode后的path

vuepress貌似本身也存在这个问题,即vuepress也没有单独处理Unicode的字符路径,感觉中文(Unicode字符)相关的问题有一堆

@Mu-Yan
Copy link

Mu-Yan commented Nov 25, 2020

嗯,我遇到问题主要是分类名是中文或者空格等,我的版本也是 1.5.7, 我也试了案例里常见的 1.5.5 版本 都存在这个问题,而后才进行的修改源码

@hellorayza
Copy link

我也发现了这个问题。
categories使用中文,从categories进入md页面后点击返回进入404.
环境:

    "vuepress": "^1.7.1",
    "vuepress-theme-reco": "^1.5.7"

btw:
hexo的categories解析规则是:

- FE
- -
- vue

成同级目录

- FE
- vue

则vue为FE的二级目录。

vuepress中,似乎只能分一级目录,用法如下:

- FE
- vue

或者是

- FE
-
- vue

能说下原因吗?或者如何快速迁移

@ATQQ
Copy link
Contributor Author

ATQQ commented Nov 29, 2020

这个中文404的问题的原因是:浏览器对直接输入的中文url准备一次编码导致匹配不到对应的路径,然后就打到了404的路由

我理解这个目录解析是很灵活的,与目录深度没关系吧

快速迁移的话 可以自己用Node写一个自动化脚本即可

@recoluan
Copy link
Member

recoluan commented Dec 1, 2020

@ATQQ @Mu-Yan

你们是不是都是在自己的服务器上配置的 Nginx,我的都是托管在第三方平台上,所以没出现你们的问题。

原来群里讨论过这个问题,好像是让 Nginx 支持中文路径即可,我个人没做过尝试,欢迎继续讨论。

@recoluan recoluan added the good first issue Good for newcomers label Dec 1, 2020
@ATQQ
Copy link
Contributor Author

ATQQ commented Dec 1, 2020

嗯,自己的服务器,部署在Nginx上,Nginx应该是支持中文的 没问题 ,如果不支持的话,就找不到对应的资源 返回的页面应该是 下面这种样子

图片

目前因为浏览器对中文资源的url进行了如下的encode,js拿到的path是没进行decode的path,所以匹配不到,就打到了配置的404路由页面

图片

解决方案应该就是 上面说的两种:

  1. 在build的时候router加入 encode后的path
  2. 客户端(浏览器)在执行router match 方法的前,先进行一下decode

只是现在需要一个方案(可以是plugin的形式),在不修改 主题/vue-router源码的情况下解决此问题

@Mu-Yan
Copy link

Mu-Yan commented Dec 2, 2020

我部署在 GitHub Pages 的

@ZhangXL-WaHaHa
Copy link

可以使用原型链修改match函数,https://blog.csdn.net/weixin_44113868/article/details/118052046

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

No branches or pull requests

5 participants