Node Reverse Proxy
这几天做GazeLabel的时候,遇到了CORS的跨域问题,主要情况是api-faceplusplus作为一个公开使用的API,居然不返回ACAO头,这样preflight就凉了...所以,面对这种素质较差的API提供商,我们选择用反代的形式解决这个问题。
由于是Nuxt的项目,所以本文以Node为主。当然为了更好的性能,Nginx也是可以反代的,还有一些类似与HAProxy的代理也可以使用。
首先,node内建的request
包肯定是首选。因为它不仅不需要额外的依赖,更好的是它可以无损把接收到的信息pipe回去。但是,express项目中,没有自带body-parser
,所以如果是需要req.body的处理,建议先安装body-parser再考虑处理后续的请求。
app.post('/api/method', (req, res) => {
req.pipe(request.post(someUrl, { json: true, body: req.body }), { end: false }).pipe(res);
}
这样,通过直接把请求pipe到request里面,然后再把结果pipe出来,效果非常好。
有个坑就是如果不确定请求的来源的METHOD,似乎不是很方便去把对应的请求方式pipe到request的特定方式下,只能通过获取req.method
或者req.url去判断并在request的option
对象里面带上method: 'GET'
。
另外一种方式是通过一个叫做node-http-proxy
的包,这个包可以很方便的代理所有某url下的请求。
const express = require('express');
const vhost = require('vhost');
const compression = require('compression');
const httpProxy = require('http-proxy');
const history = require('connect-history-api-fallback');
const app = express();
app.use(compression());
app.all('/api/*', (req, res) => {
console.log(`reverse proxy REDIRECTED ${req.url} to port 5000`);
try {
apiProxy.web(req, res, { target: 'http://localhost:5000' });
} catch (e) {
console.log('proxy failed...Ignoring and continue');
}
});
还有一种方式是CORS-anywhere
插件,但是这个插件似乎不太好控制访问的连接,感觉带来了很多不安全性,不是非常推荐。但是这个插件可以让某个url指向任意地址并带上CORS头部,感觉还是很炫酷的。似乎POST和GET都可以。
最后,如果是axios
的终极粉丝,也可以使用axios返回代理的结果,其实axios的API还是非常美好的,但是就是不支持直接pipe express的req请求,用起来就没有request那么方便了。
最后说一点题外话,body-parser
这个包如果在请求体积太大的时候会抛出Entity too large
的错误,解决方案是在参数里面带上limit: "50mb"
放宽类似的限制,就可以了。