egg.js 动态转发代理

1,208 阅读1分钟

  • 需求背景利用nodejs和consul实现注册中心和网关
  • egg.js在获取配置信息与节点后进行服务转发与路径管理
  • 实现难点没有成行的技术博客去解决这个问题

解决方案

  • 依赖http-proxy-middleware和koa2-connect

  • 重点问题application/x-www-form-urlencoded 转发代理要定制解决否则活转发失败

  • 配置文件中添加代理配置信息

  • // 忽略安全威胁csrf的防范
    config.security = {
    csrf:{
    enable: false
    } } //代理配置信息 config.proxyConfig = {};
    // add your middleware config here config.middleware = ['proxy'];

  • 在中间件中添加代理js

  • proxy.js /* * @Description: api 网关代理 * @Author: 吴文周 * @Github: gitlab.yzf.net/wuwenzhou * @Date: 2020-06-28 13:38:19 * @LastEditors: 吴文周 * @LastEditTime: 2020-08-13 18:14:32 */ const { createProxyMiddleware } = require('http-proxy-middleware'); const k2c = require('koa2-connect'); module.exports = (options,app) => {
    return async function(ctx,next) { let proxy= app.config.proxyConfig;
    try {
    const Proxy = k2c(createProxyMiddleware('/api',{ target: proxy.target,// 动态设置可以从缓存中获取更新
    pathRewrite:proxy.Rewrite,// 动态设置可以从缓存中获取更新
    changeOrigin: true,
    secure: false,
    body:ctx.request.body,
    onProxyReq:(proxyReq, req, res, options)=>{
    const contentType = proxyReq.getHeader('Content-Type'); // 特殊判断如果类型是application/x-www-form-urlencoded 转发代理需要特殊处理
    try {
    if (contentType && contentType.indexOf('application/x-www-form-urlencoded')>=0) { let body = Object.keys(options.body).map(function(key) {
    return encodeURIComponent( key ) + '=' + encodeURIComponent(options.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();
    }
    } catch (error) {
    console.log(error); } } }));
    await Proxy(ctx,next); }else{ next() } } catch (error) { console.log(error) next() } };};