记一次http-proxy-middleware的错误使用

最近新接了一个项目,需要在启动时选择代理到不同的后端地址,我就想到用 inquirer 做命令选择

  • inquirer 引用代码
// inquirer 版本 5.2.0
function ask() {
  var proxys = require('./serverProvider')
  return inquirer.prompt([
    {name: 'prefix', type: 'input', message: '请输入prefix(如果有)'},
    {name: 'target', type: 'list', message: '请选择代理的地址', choices: Object.values(proxys)}
  ])
    .then(answers => {
      app.use(proxyMiddleware(answers['prefix'], {
        target: answers['target'],
        changeOrigin: true
      }))
      resolve()
    })
    .catch(e => {
      reject(e)
    })
}
  • serverProvider 文件
module.exports = {
  provider1: '172.27.49.11:8081', // 小明
  provider2: '172.27.49.10:8081', // 小红
}

执行 npm run dev 后,报错:

《记一次http-proxy-middleware的错误使用》 WX20180425-162106@2x.png

解决问题

  1. 看到所属包是 requires-port , 调用该包的库是 http-proxy-middleware, 看到该包版本为0.17.3,就想着是不是版本太低的 bug,逐使用 npm update | grep http-proxy-middleware,发现最新也就0.17.4,基本可排除版本问题。
  2. 那就看该库哪里报错吧,根据提示找到node_models/requires-port/index.js 13行
module.exports = function required(port, protocol) {
  protocol = protocol.split(':')[0];
  ...
}

可以看到是传进来的protocol为空,所以执行 split 操作时报错(其实细心点这时已经可以知道错误在哪了)
然后在node_models全局搜’requires-port’(或者看报错第二行),定位到node_models/http-proxy/lib/http-proxy/common.js 109行

if (options.changeOrigin) {
    outgoing.headers.host =
      required(outgoing.port, options[forward || 'target'].protocol) && !hasPort(outgoing.host)
        ? outgoing.host + ':' + outgoing.port
        : outgoing.host;
  }

是options[forward || ‘target’].protocol为undefined,所以导致调用 requires-port 出错,打印出 options 后发现是 target: xxxx,是个 String 类型,之后将这个改为含有protocol的对象就正常执行了。

后续

发现之前项目也是target为String的,但没有报错,对比后发现原来是写的后端地址没有写上协议(心酸~~),补充后String类型也是可以的。

还有一个关于inquirer的补充吧,因为后端地址现在是对象的形式,只能获取value,但不能在选择的时候就与是哪个同事的地址匹配,所以改成Map形式

// 更改后的serverProvider
const map = new Map()
map.set('小明', '172.27.49.11:8081')
map.set('小红', '172.27.49.10:8081')

// TODO 可以做成一个类,添加validate方法校验
module.exports = Array.from(map)
// 修改引用代码
function ask() {
  var proxys = require('./serverProvider')
  return inquirer.prompt([
    {name: 'prefix', type: 'input', message: '请输入prefix(如果有)'},
    {name: 'target', type: 'list', message: '请选择代理的地址', choices: proxys.map(it => String(it))}
  ])
    .then(answers => {
      app.use(proxyMiddleware(answers['prefix'], {
        target: answers['target'].split(',')[1],
        changeOrigin: true
      }))
    })

}

总结

这个错误其实是一个低级错误,不应该犯的,将这篇文章写出来是为了分享我的问题解决方式,如有哪些地方可以改进的也可以留下评论。

    原文作者:天驱丶
    原文地址: https://www.jianshu.com/p/d162fdee5cfd
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞