zoukankan      html  css  js  c++  java
  • Koa下http代理

    前言

    最近做管理后台的重构或者说重做. 至于为什么要重构.
    随意的解释:

    1. 是原来写的人走了.

    客观的解释:

    1. 用的人觉得不好用
    2. 维护的人员找不到北

    再多一点解释:

    1. express + ejs的混合编写
      • 单独抽象了Router层, 定义了controller层, service层, 但是强行绑定, 耦合很紧密
      • 中间件过度使用, 本意想简化操作, 反而编程负担
      • 服务端定义了渲染模板, 前端又有模板, 额
      • 引入ts, 但是很多都是any, 接口很多都是直接把query或者body参数直接使用, 非常难跟踪数据
      • views未按照功能分文件夹, 全部在一个文件夹下, 头晕的厉害
      • 后台配置不合理, 即使是菜单这种配置也是完全一样的几份
    2. 前端杂乱
      • jquery编写, 本身并无问题, 没有模块化, 出现代码多页面混用, 一处修改, 可能多页面出错
      • 体验很差, 测试人员和开发人员都不一定能正常操作

    额外说两句, 这里的express + ejs的项目属于前端项目, 后台有很多nodejs编写的形式微服务的服务.

    因为是后台管理项目, 美观要求并不是那么高. 我的规划是.

    基于koa的node中间层

    1. 授权管理
    2. ACL管理, 这里我们自己编写的轻量级的权限控制.
    3. 文件上传(阿里) 和其他可能需要定制的处理, 比如使用文件批量上传数据的处理
    4. 请求转发

    前端项目
    使用 create-react-app + react-app-rewired + ant + mobx 构建项目,
    ant design已经基本够用, 实际上mobx都可以不用.

    这里就有两个项目项目了, 一个ui项目, 一个中间层api项目.

    开发模式下, ui项目是通过dev-server启动的, 会通过代理转发请求到中间层api项目, 中间层api项目再转发到实际的服务. 这一切看起来都很美好, 也没毛病.

    问题

    我随手拈来, 配置好, 开始请求. 就泪奔了. 请求死活过不去.

    各种中间件尝试

    express下面有很好用的http-proxy-middleware, 但是koa并没有, koa官方推荐的是koa-proxies 和koa-better-http-proxy, 自己搜索发现 koa-proxy下载量和star都还要高一些, 于是自己就开始挨个试试, 均失败.

    开始怀疑是版本问题, 查看均是支持的, 而且debug确实执行了请求发送, debug进入源码发现 Socket hang up.

    自己封装

    后来检查源码, 其实都是基于http-proxy进行的封装, 于是参考别人的代码, 自己简单的封装了一个版本, 进行debug, 结果依旧,

    koa-connect

    后来搜索发现, koa下能使用express的中间件, 需要通过转换, 这个中间件就是koa-connect, 于是进行切换, 结果还是失败, 心疼

    http-proxy 生命周期拦截

    接着尝试, 在http-proxy的各个生命周期进行拦截, 成效也不大, 倒是了解了一下http-proxy

    x-www-form-urlencoded

    我们的接口全部都是post调用的,而且接受的数据格式都是x-www-form-urlencoded, 偶尔一次发现, 使用get居然转发到了服务器, 只是提示不允许get调用, 其实说明已经能联通, 但是post却是过不去. 那就说明问题很可能处在数据传递的格式.

    百度,bing和google搜索

    发现了这篇文章,
    http-proxy-middleware nodejs post请求超时问题 x-www-form-urlencoded
    我把代码提前了, 结果真的是ok了, 我的眼泪啊.

    但是, 不能这样啊, 我的auth拦截肯定会先于proxy, auth之前肯定还有bodyParser, session等中间件, 大哥这可不行啊.

    继续搜索 edit-post-parameters-prior-to-forwarding-to-a-proxy-target-and-sending-response

       onProxyReq(proxyReq, req, res) {
            if ( req.method == "POST" && req.body ) {
                // Add req.body logic here if needed....
    
               // ....
    
                // Remove body-parser body object from the request
                if ( req.body ) delete req.body;
    
                // Make any needed POST parameter changes
                let body = new Object();
    
                body.filename = 'reports/statistics/summary_2016.pdf';
                body.routeid = 's003b012d002';
                body.authid = 'bac02c1d-258a-4177-9da6-862580154960';
    
                // URI encode JSON object
                body = Object.keys( body ).map(function( key ) {
                    return encodeURIComponent( key ) + '=' + encodeURIComponent( body[ key ])
                }).join('&');
    
                // Update header
                proxyReq.setHeader( 'content-type', 'application/x-www-form-urlencoded' );
                proxyReq.setHeader( 'content-length', body.length );
    
                // Write out body changes to the proxyReq stream
                proxyReq.write( body );
                proxyReq.end();
            }
        }
    

    看到重写了content-type和content-length, 我就笑了. 还是自己太天真, 没理解好这个onProxyReq方法, 于是我也这么重写, 再提前其他中间件, 就没有问题了.

    我真的就能苦笑了, 还好解决了问题. 关于http-proxy打算有时间深入看一看, 值得拥有.

  • 相关阅读:
    USART串口通信实验
    EXTI 外部中断
    NVIC中断优先级管理
    实验1 跑马灯实验
    redis集群部署---一台主机
    zookeeper服务启动报错---Error contacting service. It is probably not running.
    shell脚本学习笔记
    最短路径算法——Floyd算法
    一篇文章学懂Shell脚本(摘抄)
    VIM空格和TAB转换
  • 原文地址:https://www.cnblogs.com/cloud-/p/9762901.html
Copyright © 2011-2022 走看看