ngx_lua学习笔记 -- capture + proxy 实现httpclient(转发学习记录)

原理
ngx_lua本身不提供httpclient功能,但提供了ngx.location.capture接口。这个接口可以发送一个子请求(subrequest),并获取子请求的响应结果。子请求可以调用lua,或者返回文件,甚至通过proxy_pass访问另一个地址。

关键就在这里!如果我们使用proxy_pass机制结合subrequest,不就能实现http接口请求了吗?

且慢!

一般来说,httpclient要求能够指定method,scheme,域名,端口,请求头,以及数据。但默认的subrequest将继承所有当前请求的信息。好在ngx.location.capture接口支持指定method和data。那么只要搞定scheme,域名,端口,请求头就可以了。

实现
使用过nginx的proxy_pass的同学都知道,proxy_pass支持从变量中获取值(如常见的proxy_pass s c h e m e : / / x x x scheme://xxx scheme://xxxrequest_uri;)。而rewrite能够利用捕获组设置变量,所以,我们可以在nginx的配置文件中加入这么一条location规则:

location /proxy/ {
     internal;
    rewrite ^/proxy/(https?)/([^/]+)/(\d+)/(.*)     /$ break;
    proxy_pass      $://$2:$3;
}

第一行,指定规则为internal规则,防止外部请求命中此规则
第二行,使用rewrite将地址中的scheme,host,port匹配出来;使用break终止匹配,不再检查其它location
第三行,使用proxy_pass将scheme,host,port拼装成服务器地址

这样,我们要请求如https://www.example.com:443/foo/bar时,只需要在lua代码中构造一个子请求,地址为/proxy/https/www.example.com/443/foo/bar即可。

接下来就是header问题,通过ngx.req.set_header可以在lua中添加需要的请求头。

由于header的继承性,我们需要考虑来自客户端的哪些header不能被传递到远端接口中:
Host: 因为proxy_pass默认会重写host,所以无需处理(在常规的proxy_pass中,可能需要使用proxy_set_header命令修正Host头)
Content-Type: 如果来自客户端的请求类型为POST,需要将该头去掉
Content-Length: 同上
Accept-Encoding: 绝大多数时候,浏览器接受gzip, deflate格式的压缩,如果远端接口启用了压缩,此头将导致返回的数据格式被压缩过,从而lua无法正确处理。因此需要去掉此头
Cookie: 涉及到隐私问题,所以这个头也需要去掉
 通过ngx.req.clear_header可以将需要去掉的头去掉。注意为了不影响后续处理,所有被去掉/改写的头应该被恢复,所有被添加的头应该被去掉。

下面是一个简单的示例代码:

– POST https://www.example.com:443/foo/bar?hello=world

ngx.req.set_header("Content-Type", "application/json;charset=utf8");
ngx.req.set_header("Accept", "application/json");
 
local res = ngx.location.capture('/proxy/https/www.example.com/443/foo/bar', {
    method = ngx.HTTP_POST,
    body = body,
    args = {hello = 'world'}
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值