环宇的Blog

nginx+express做一个简易代理服务

用 NGINX + EXPRESS + Let’s Encrypt 构建HTTPS接口服务

最近想搞个小程序,需要查询下github的api服务。小程序的请求是走的小程序提供的api,没有跨域问题,不过需要配置下请求域名白名单。

本以为可以在小程序后台配置一下域名之后直接请求,结果发现小程序后台配置里只允许设备案过的域名,GitHub显然不可能有国内备案。

还好自己也有服务器+域名,自己动手搭一个。而且小程序要求全是HTTPS的,还是有遇到一点小坑。

方案

其实NGINX本身就可以完成反向代理功能,不过考虑到以后可能还想在这个基础上做一些别的东西,还是来个可编程的服务比较好。出于简便性考虑直接无脑选了express。

开个新的二级域名,因为只有一台云虚拟机,80/443端口已经被NGINX占用了,那就NGINX转发给express吧,所以整个结构就是NGINX反向代理express(这个express服务又是个对github的反向代理,真巧……)

NGINX加一个新配置,监听80端口,对 / 全转发去本机的3000端口,完事。

1
2
3
4
5
6
7
8
server {
server_name 域名马赛克;
listen 80;

location / {
proxy_pass http://127.0.0.1:3000;
}
}

然后用Let’s Encrypt搞一下HTTPS,用 certbot 这个工具,直接选服务器软件和系统,可以自动帮你完成配置HTTPS。

用express写个hello world,再全局安装pm2,启动我们的express程序,访问域名即可看到hello world,基本搞定。接下来再选个反向代理中间件,配置下target为api.github.com,大功告成。

超时

结果接下来实际测试发现炸了……

很多请求报504 网关超时

一通搜索,发现很多是给NGINX和PHP结合的方案用的(后仰:什么叫全宇宙最好的语言啊),不过差不多,都是说设置上游超时时间。

创建 /etc/nginx/conf.d/timeout.conf ,加上以下内容:

1
2
3
4
proxy_connect_timeout       600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

然后再试,发现还是容易出现504。

就需要细节排查问题了,先查nginx的日志,access.log和error.log,发现这个504在nginx的错误日志里是没有的,access里有记录express程序给返回了200和504,问题应该是出在express里。

接下来打印pm2的日志,发现错误信息是 Error occurred while trying to proxy request xxxxx from 127.0.0.1:xxxx to https://api.github.com (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)

打开这个链接,这个错误信息是:ECONNREFUSED (Connection refused): No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host.

目标机器主动拒绝了请求,这说明Github应该是觉得这个请求不正常,想了下估计是没带一个浏览器的头,伪装成浏览器应该就好。

配置下代理的headers,再重启服务,终于OK了