美文网首页大前端刷级之路
记一次http-proxy-middleware的错误使用

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

作者: 天驱丶 | 来源:发表于2018-04-25 16:45 被阅读4次

    最近新接了一个项目,需要在启动时选择代理到不同的后端地址,我就想到用 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 后,报错:

    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
          }))
        })
    
    }
    

    总结

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

    相关文章

      网友评论

        本文标题:记一次http-proxy-middleware的错误使用

        本文链接:https://www.haomeiwen.com/subject/jjjylftx.html