egg是否有类似http-proxy-middleware的转发中间件

Created on 16 May 2017  ·  25Comments  ·  Source: eggjs/egg

我们使用egg去转发一些前端请求,原本使用curl去转发,但是做的过程中发现要用支持图片、excel等多种格式。尤其是excel格式,contentType改为'application/xml'之后是能下载,但是名字之类都不是想要的。试了下http-proxy-middleware,它对格式都进行了处理,但是它不支持koa和egg。想问下egg有没有类似的中间件

Most helpful comment

最近在写新项目,需要用 node 进行多个接口服务代理组合,针对代理可以通过以下方式解决

//  app/middleware/httpProxy.js
const httpProxy = require('http-proxy-middleware');
const k2c = require('koa2-connect');
const pathToRegexp = require('path-to-regexp');

module.exports = (options) => {
  const test1Proxy = k2c(httpProxy({
    target: 'http://test1.com',
    changeOrigin: true,
  }));

 const test2Proxy = k2c(httpProxy({
    target: 'http://test1.com',
    changeOrigin: true,
  }));

  return async function(ctx, next) {
    if (pathToRegexp(/api\/v1/test1/).exec(ctx.request.url)) {
      test1Proxy(ctx, next);
    } else if (pathToRegexp(/api\/v1/test2/).exec(ctx.request.url)) {
      test2Proxy(ctx, next);
    } {
      await next();
    }
  };
};

当然需要在 bodyparser 之前引入

// app.js
module.exports = app => {
  app.config.coreMiddleware.unshift('httpProxy');
};

All 25 comments

目前没有,可以参考 https://github.com/popomore/koa-proxy ,用 egg 的 curl 写一个类似的插件。

koa-proxy 这个有点 hack,慎用。

可以按照 http-proxy-middleware 自行实现

测试可行

const c2k = require('koa-connect');
const proxy = require('http-proxy-middleware');

module.exports = app => {
  app.get('/api/v4/news/**', function* (next) {
    yield c2k(proxy({ target: this.app.config.api.newApiUrl, changeOrigin: true }))(this, next);
  });
};

@wangguohao app.get的路径调通了,但是post接口失败了,您能试一下吗?要怎么写?

请求到了服务端,但是出现了异常,我推断可能是body流被读过了

updated solution:
_proxy的代码要写在 bodyParser 前面_

@atian25,你好。。想请教一下用 curl 改写,如何把 cookie 塞进去呢?

ctx.curl(link, {
  headers: {
    cookie,
  }
}

这样子好像不可以

curl 底层是 https://www.npmjs.com/package/urllib ,你可以研究下。

是不是你 cookie 的格式不对啥的,抓包看看。

@atian25 …… 多谢指点,是格式有点问题,后来直接把 header 全部塞进去就OK了。不过这就又有一个疑问想请教一下,如果想获取所有的 cookie 键值对,而 ctx.cookies 并不是一个可遍历对象,那就只能通过解析 header 里的 cookie 字符串了?

可以看下源码

也是。。不觉成了伸手党了。。

最近在写新项目,需要用 node 进行多个接口服务代理组合,针对代理可以通过以下方式解决

//  app/middleware/httpProxy.js
const httpProxy = require('http-proxy-middleware');
const k2c = require('koa2-connect');
const pathToRegexp = require('path-to-regexp');

module.exports = (options) => {
  const test1Proxy = k2c(httpProxy({
    target: 'http://test1.com',
    changeOrigin: true,
  }));

 const test2Proxy = k2c(httpProxy({
    target: 'http://test1.com',
    changeOrigin: true,
  }));

  return async function(ctx, next) {
    if (pathToRegexp(/api\/v1/test1/).exec(ctx.request.url)) {
      test1Proxy(ctx, next);
    } else if (pathToRegexp(/api\/v1/test2/).exec(ctx.request.url)) {
      test2Proxy(ctx, next);
    } {
      await next();
    }
  };
};

当然需要在 bodyparser 之前引入

// app.js
module.exports = app => {
  app.config.coreMiddleware.unshift('httpProxy');
};

@wangguohao 可以封装成插件分享出来

@atian25 一般公司内部都会封装这样的包吧 阿里怎么没有开源

welcome to use koa2-proxy-middleware

@wangguohao app.get的路径调通了,但是post接口失败了,您能试一下吗?要怎么写?

请求到了服务端,但是出现了异常,我推断可能是body流被读过了

updated solution:
_proxy的代码要写在 bodyParser 前面_
@miaojiuchen 你好,post请求需要怎么请求呢? get请求是通得,post请求过不去????

@zheng199512 proxy的代码要写在 bodyParser 前面

app.use(c2k(httpProxy('/zheng', { target: 'http://www.icodehub.cn:7001', changeOrigin: true })));

写成这样是post和get请求都可以用的,这样写是符合规则的么?
我在想一个问题,两个月前有更新egg-proxy,能够按照match规则进行转发,貌似host和url是不能写多个的,有没有办法可以设置多个呢???请教一下~
@atian25 大佬,@miaojiuchen 大佬,

egg-proxy 并不是官方维护的插件,你可以去给作者提下 issue 交流下。https://github.com/xyeric/egg-proxy#readme

附上配置设置多个服务代理的方法,哇,藏的好深,感谢大佬的贡献,感谢大佬们的解答,谢谢,谢谢。https://github.com/xyeric/egg-proxy/issues/2

可以给对方 PR 更新到 README

请问下怎么对转发的请求添加参数呢?比如:加上 cookie


知道了,可以修改ctx.req.headers

需要去理解下 stream。

bodyParser 和 multipart 都会消费 ctx.req 这个 stream,所以你的 proxy 要不只能在它们之前,要不就配置下 ignore 掉。

但你在 proxy 里面又想校验,那就放到 bodyParser 和 multipart 之后,拿到它们已经消费好的东西,校验后,再自行传递到后面去。

@wangguohao 为啥要在bodyparser 之前引入,放在config里面的config.middleware = [
'httpProxy'
];

会有什么问题?

需要去理解下 stream。

bodyParser 和 multipart 都会消费 ctx.req 这个 stream,所以你的 proxy 要不只能在它们之前,要不就配置下 ignore 掉。

但你在 proxy 里面又想校验,那就放到 bodyParser 和 multipart 之后,拿到它们已经消费好的东西,校验后,再自行传递到后面去。

已经用这个方法实现了校验。原理就是每次消费后再将stream重新放入buffer。

const rawBody = ctx.request.rawBody;
if (rawBody) {
const buffer = new ReadableStream();
buffer.push(rawBody);
buffer.push(null);

proxy = k2c(
httpProxy(
Object.assign({}, options, {
buffer,
})
)
);
}

可以看下 egg-http-proxy-middleware

  • middleware 而非 plugin,保障 middleware 的执行顺序
  • 内部处理了 bodyParser 问题
  • 100% typescript
  • 配置式,配置同 webpack-dev-server
Was this page helpful?
0 / 5 - 0 ratings