route.query +号变空格问题记录

1,652 阅读2分钟

背景

最近有个新项目使用vuecli4 vue3 来开发,其中一个需求是从url解析出参数,然后发送后端解密查询。开发时一直使用明文,所以未出现这种情况。在转测后使用加密 &content={"orderNo":"aaaaa+bbbb"};结果route.query 解析成 content={"orderNo":"aaaaa bbbb"}。惊不惊喜,意不意外?难道祖师爷写了bug?

思考方向

  • 编码问题
  • 祖师爷写bug 我赶快兴冲冲的去 fork vue-router.我要在简历上写上 vue-router: contributor.

源码分析

  • 全局找到 query。定位到 src/util/query.js。
const encode = str =>
  encodeURIComponent(str)
    .replace(encodeReserveRE, encodeReserveReplacer)
    .replace(commaRE, ',')

export function decode (str: string) {
  try {
    return decodeURIComponent(str)
  } catch (err) {
    if (process.env.NODE_ENV !== 'production') {
      warn(false, `Error decoding "${str}". Leaving it intact.`)
    }
  }
  return str
}

控制台测试编码问题: encodeURIComponent、decodeURIComponent 对于 + 号也是正确编码解码的。那只能排除编码问题。现在就剩下 祖师爷写bug 了。

function parseQuery (query: string): Dictionary<string> {
  const res = {}

  query = query.trim().replace(/^(\?|#|&)/, '')

  if (!query) {
    return res
  }

  query.split('&').forEach(param => {
    const parts = param.replace(/\+/g, ' ').split('=')
    const key = decode(parts.shift())
    const val = parts.length > 0 ? decode(parts.join('=')) : null

    if (res[key] === undefined) {
      res[key] = val
    } else if (Array.isArray(res[key])) {
      res[key].push(val)
    } else {
      res[key] = [res[key], val]
    }
  })

  return res
}

我们发现了问题所在:param.replace(/+/g, ' ').split('=')。大家都明白了,问题出在这里。祖师爷为什么要特殊处理 + 号? 到这里还是想不明白为什么要这样做, 难道是 param的问题?那我们就接着找param 到底是什么。经过一步一步往上找,我们在 src/util/path.js

export function parsePath (path: string): {
  path: string;
  query: string;
  hash: string;
} {
  let hash = ''
  let query = ''

  const hashIndex = path.indexOf('#')
  if (hashIndex >= 0) {
    hash = path.slice(hashIndex)
    path = path.slice(0, hashIndex)
  }

  const queryIndex = path.indexOf('?')
  if (queryIndex >= 0) {
    query = path.slice(queryIndex + 1)
    path = path.slice(0, queryIndex)
  }

  return {
    path,
    query,
    hash
  }
}

这个 query 就是 src/util/lacation.js normalizeLocation() parsePath() 传过来的 location.search 里面的参数(aaa=bb&cc=dd)。那么到这里,我更相信肯定有我不知道的未知原因,而不是说 祖师爷写bug了。于是我又百度了。找到了阮一峰老师的关于URL编码。好吗 一通看下来,url编码虽然混乱,但是和 param.replace(/+/g, ' ') 这个操作有什么关系呢。没办法,只能百度一个一个往下点。直到我看到这句话

url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,如何是好?

可能在服务器无法获得正确的参数值。。。服务端,我问了我们的java:都是正常可以获取的啊!只要你传的对,我肯定能获取啊。 nice 对就是这样。没毛病!

求助

哪位大佬能告诉我下服务端到底用的什么解码格式 获取不了正确的参数?