需求背景
需求是使用 nginx 做一个 https 服务的代理
nginx 收到 http 请求后,需要修改 body 中的某些参数值,然后将修改后的数据发送到目标服务器(https)
本来以为很简单的需求,结果中间出现了不少岔子,这里记录一下
知识点汇总
location = xxx {}
是精确匹配,location xxx {}
是前缀匹配。- 用 lua 脚本处理请求时,如果脚本找不到,客户端看到的是 404 not found,和路由配置错了一个样。
- lua-resty-http 模块管理员权限直接安装就行(不需要和 nginx 一起编译)。
- httpc:request_uri 请求时,必要的配置是
resolver
(做 dns 解析);https 请求时,加上 ssl_verify = false 可以避免 https 证书带来的问题(python requests 包也有这个参数,但是不推荐使用,不安全)。 - 像这种靠近底层的工具如果修改了 http 请求的 body 时,一定要关注是否已经设置过
Content-Length
这个 header 了,可以去掉或者重新设置。否则可能造成的问题是 数据异常截断 或者 莫名奇妙的等待。 ngx.req.get_body_data()
不能可靠的获取到 body 数据,要结合ngx.req.get_body_file()
详细问题
问题1:配置了 location
但是显示 404
代码如下
location = /aigw {
content_by_lua_file conf/lua/aigw.lua;
}
这个代码先后改了两次,实际有两个原因客户端都会显示 404
location =
是精确匹配,请求有后缀就找不到了- 如果 conf/lua/aigw.lua 文件找不到,也不会提示内部错误信息,客户端看到的也是 404 问题
问题 2:module 'resty.http' not found:
使用如下命令安装,注意必须是 sudo 权限下,否则不行
sudo apt-get update
sudo apt-get install -y luarocks
sudo luarocks install lua-resty-http
问题 3:no resolver defined to resolve "xxxxx"
问题代码如下,这个错误是下面 err 的值
local res, err = httpc:request_uri(forwardUrl, {
...
})
解决方案:这个错误表明 NGINX 没有配置 DNS 解析器来解析 xxxxx 域名。你需要在 NGINX 配置文件中添加一个 resolver 指令来指定 DNS 服务器。
在 nginx.conf 文件的 http 或 server 块中添加以下内容:
http {
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 其他配置...
}
8.8.8.8 和 8.8.4.4 是 Google 的公共 DNS 服务器,你也可以使用其他 DNS 服务器。
添加后,重新加载 NGINX 配置:
sudo nginx -s reload
问题 4:unable to get local issuer certificate
这也是发送请求时的错误信息。
这个错误表明 NGINX 无法验证目标 HTTPS 服务器的 SSL 证书。下面是两种解决方案,我才用了第一种
-
忽略 SSL 证书验证(不推荐用于生产环境): 在 httpc:request_uri 调用中添加 ssl_verify = false 参数。
local res, err = httpc:request_uri(forwardUrl, { method = ngx.req.get_method(), body = body_data, headers = ngx.req.