前端同学需要一个上传文件的后端做一些调试,我刚好有,就给她用了。然后遇到跨域问题,一般来说我会在 PHP 里解决,不过这次我想挑战一下 nginx,于是找到这个答案。照做之后,OPTIONS
请求按照预期返回了正确的头,但是 POST
不行。
于是我在群里请教同事,结果被老板批评:
- 在 nginx 里,“IF is evil”,因为要在一些特定条件下,它的行为会跟预期完全相反;有时候甚至会引起 segfault
- 我厂是 OpenResty,没理由不用 OpenResty
行吧,本来就是为了跨出舒适区,不妨走远一点,OpenResty 就 OpenResty。
0. 用 OpenResty 替换 Nginx
我的系统是 Ubuntu 18.04,所以先按照 官方文档 安装最新版本的 OpenResty。
安装完成之后,可以通过 service --status-all
查看服务列表,不出意外的话,能看到 openresty 服务。
停掉 nginx,然后启动 openresty:
service nginx stop
service openresty start
此时 openresty 的配置位于 /usr/local/openresty/nginx/conf/nginx.conf
,默认的 web 服务地址是 /usr/local/openresty/nginx/html/
,所以我们需要修改一下,以便继续使用 /var/www/html
,也就是之前 nginx 的网页文件。
1. 继续使用 nginx 的配置
修改配置的方式很简单,OpenResty 本来也兼容 nginx 的配置。对于我而言,最简单的做法是干掉 server
的部分,然后加载 nginx 的网站配置,也就是这两句:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
此处会有个小问题:PHP 网站的配置里需要加载 snippets/astcgi-php.conf
,默认使用的是相对路径,需要改成绝对路径 /etc/nginx/snippets/fastcgi-php.conf
。
至于其它配置,比如 gzip
、ssl
等,酌情拷过来即可。
2. 增加配置以自动输出请求头
最后就是写 lua,这部分难度不大,基本就是普通的 lua 和 nginx lua API。写好的配置是这样的:
location / {
access_by_lua_block {
if ngx.req.get_method() == 'POST' then
ngx.header['Access-Control-Allow-Origin'] = '*';
ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';
ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
ngx.header['Access-Control-Allow-Expose-Headers'] = 'Content-Length,Content-Range';
elseif ngx.req.get_method() == 'OPTIONS' then
ngx.header['Access-Control-Allow-Origin'] = '*';
ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';
ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';
ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
ngx.header['Access-Control-Max-Age'] = 1728000;
ngx.header['Content-Type'] = 'text/plain; charset=utf-8';
return 204;
end
}
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.php$args;
}
首先,使用 access_by_lua_block
添加 lua 代码块。这里注意,一定要用 access_by_lua_block
,不能用 content_by_lua_block
,因为我们后面还要用 proxy_pass
把请求反向代理给 php-fpm 处理,而 content_by_lua_block
就直接返回了。
然后,因为要添加 headers,所以要在能输出其它内容前先输出头。所以这个代码块要放在最前面,前面不能有其它输出。
3. 总结
需求不大,代码也比较简单,不过还是花了大约一天的时间调试。将来可能会写更多的 OpenResty lua,到时候再慢慢分享咯。
另外我也搞不清楚为啥 nginx 这么流行的一个软件竟然有 if
这种问题。有知道的同学请指教。
欢迎吐槽,共同进步