向外部 https 服务发起请求 [was]lua-resty-http POST JSON 数据

2,636 views
Skip to first unread message

Zoom.Quiet

unread,
Aug 10, 2014, 10:55:39 AM8/10/14
to openresty
> On Sun, Aug 10, 2014 at 2:41 AM, Yichun Zhang (agentzh)
> <age...@gmail.com> wrote:
..
>> James Hurst 的 lua-resty-http 库的文档中的“Synopsis”一节里的代码示例确实不够完整,我刚给他提了一个
>> pull request,完善了一下那里的代码示例:
>>
>> https://github.com/pintsized/lua-resty-http/pull/18/files
>>
>> 加上了 resolver 配置指令和恰当的错误处理。
>
> 现在春哥一提醒,发现已经有当年期待的对应简化模块,
> 只是少了模块外的一行配置.
..
> 加上,一切KO...
> 本地测试就有了全新的汇报:
>
> $ curl -d "uri=https://docs.google.com/forms/d/1TBJNar54XKhMu_nRaES5ByPv0078hh0GV0sD5JPCZGU/viewform"
> 23.239.0.15:10080/=/gl
> request_method: POST
...

> {"error":{"errors":[{"domain":"global","reason":"sslRequired","message":"SSL
> is required to perform this operation."}],"code":403,"message":"SSL is
> required to perform this operation."}}

目测 当前 lua-resty-http 不支持 https
那么可行的方案就是先手工用 cosocket 接口,构造一个 https 的客户端,
这事儿,暂时超过俺的能力范畴,

大家是否有现成的实例?




--
人生苦短, Pythonic! 冗余不做,日子甭过!备份不做,十恶不赦!
KM keep growing environment culture which promoting organization be learnning!
俺: http://zoomquiet.io
许: http://creativecommons.org/licenses/by-sa/2.5/cn/

Yichun Zhang (agentzh)

unread,
Aug 10, 2014, 2:50:19 PM8/10/14
to openresty
Hello!

2014-08-10 7:55 GMT-07:00 Zoom.Quiet:
> 目测 当前 lua-resty-http 不支持 https
> 那么可行的方案就是先手工用 cosocket 接口,构造一个 https 的客户端,
> 这事儿,暂时超过俺的能力范畴,
>

ngx_lua 模块刚刚实现了 SSL cosocket API,尚未包含在现有的任何发布中,所以 lua-resty-http 也没有对
https 的现成的支持。不过 lua-resty-http 有一个分支已经使用新的 SSL cosocket 支持实现了 https:

https://github.com/hamishforbes/lua-resty-http/tree/ssl-cosocket

更多细节可以参见下面这个 ticket 里的讨论:

https://github.com/pintsized/lua-resty-http/issues/11

对于现有的 OpenResty 和 ngx_lua 发布,可以使用 ngx.location.capture + ngx_proxy 进行
https 后端通信,见这里给出的一个通过 https 访问 Google 搜索的代码示例:

https://github.com/openresty/lua-nginx-module/issues/178#issuecomment-48390360

Regards,
-agentzh

Heero Zhang

unread,
Aug 11, 2014, 1:00:09 AM8/11/14
to open...@googlegroups.com
问个和题目无关的问题,我是通过这个方法访问https的,但一直会报个握手错误,一直没找到为什么,不知道大家是否遇到过?不影响正常使用,只是每次都会报个错。

2014/08/11 12:55:28 [alert] 5164#0: *4 ignoring stale global SSL error (SSL: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE
:nested asn1 error error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:Field=n, Type=RSA error:04093004:rsa routines:OLD_RSA_PRIV_DECODE:RSA lib error:0606506D:digital enve
lope routines:EVP_DecryptFinal_ex:wrong final block length error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length) while SSL handshaking to upstream, client: 127.0.0.1,  HTTP/1.1", subrequest: "/ios_validation", upstream: "https://17.154.66.159:443/verifyReceipt"

upstream ios_verify_server  {
}

    location = /ios_validation {
        internal;

        proxy_redirect off;
        proxy_ssl_session_reuse off; 

        proxy_set_header Host "buy.itunes.apple.com";

        proxy_read_timeout 45s;
        proxy_send_timeout 45s;
        proxy_connect_timeout 45s;
    }

在 2014年8月11日星期一UTC+8上午2时50分19秒,agentzh写道:

sunjun

unread,
Aug 11, 2014, 1:20:30 AM8/11/14
to openresty
 
问题应该是你proxy_set_header Host "buy.itunes.apple.com";
请求的域名sandbox.itunes.apple.com 根本就不匹配吧
 
 

 
发件人: Heero Zhang
发送时间: 2014-08-11 13:00
收件人: openresty
主题: Re: [openresty] 向外部 https 服务发起请求 [was]lua-resty-http POST JSON 数据
--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

Heero Zhang

unread,
Aug 11, 2014, 2:21:15 AM8/11/14
to open...@googlegroups.com, sun...@linko2o.com
感谢回复

>改成 :proxy_pass https://sandbox.itunes.apple.com/verifyReceipt; 试试
没有pass到直接的地址是因为我想用upstream,这样反复请求速度会快些,应该是这样吧?

>请求的域名sandbox.itunes.apple.com 根本就不匹配吧
修改过,确定和这条没关系。这个只是Host来着,给对方服务器判断来源用的,应该不会影响SSL握手


在 2014年8月11日星期一UTC+8下午1时20分30秒,sunjun写道:

Zoom.Quiet

unread,
Aug 11, 2014, 6:08:24 AM8/11/14
to openresty
On Mon, Aug 11, 2014 at 2:50 AM, Yichun Zhang (agentzh)
<age...@gmail.com> wrote:
> Hello!
>
> 2014-08-10 7:55 GMT-07:00 Zoom.Quiet:
>> 目测 当前 lua-resty-http 不支持 https
>> 那么可行的方案就是先手工用 cosocket 接口,构造一个 https 的客户端,
>> 这事儿,暂时超过俺的能力范畴,
>>
>
> ngx_lua 模块刚刚实现了 SSL cosocket API,尚未包含在现有的任何发布中,所以 lua-resty-http 也没有对
> https 的现成的支持。不过 lua-resty-http 有一个分支已经使用新的 SSL cosocket 支持实现了 https:
>
> https://github.com/hamishforbes/lua-resty-http/tree/ssl-cosocket
>
> 更多细节可以参见下面这个 ticket 里的讨论:
>
> https://github.com/pintsized/lua-resty-http/issues/11
>

soo happy 的节奏,不过,现在用不了,只能口水ing...

> 对于现有的 OpenResty 和 ngx_lua 发布,可以使用 ngx.location.capture + ngx_proxy 进行
> https 后端通信,见这里给出的一个通过 https 访问 Google 搜索的代码示例:
>
> https://github.com/openresty/lua-nginx-module/issues/178#issuecomment-48390360
>

嗯嗯嗯,这就是两年前,讨论线索最后推荐的 cosocket 数据流思路哪!
又参考了以下代码:

HttpLuaModule - Nginx Community
http://wiki.nginx.org/HttpLuaModule#ngx.location.capture
...
res = ngx.location.capture(
'/foo/bar',
{ method = ngx.HTTP_POST, body = 'hello, world' }
)

Posting to goo.gl from Android - Stack Overflow
http://stackoverflow.com/questions/6052156/posting-to-goo-gl-from-android
...
post.setEntity(new StringEntity("{\"longUrl\": \"http://www.google.com/\"}"));
...
post.setHeader("Content-Type", "application/json");

解决了问题 ;-)
配置中追加:
location /googleapis {
internal;
rewrite ^/googleapis(.*) $1 break;
# to disable gzip compression on the backend
proxy_set_header Accept-Encoding '';
proxy_set_header Content-Type 'application/json';
#proxy_set_header contentType 'application/x-www-form-urlencoded';
proxy_pass https://www.googleapis.com;
}
lua 中变成:
SURI = "https://www.googleapis.com/urlshortener/v1/url"
ngx.say("uri\t", URI)
--DATA = "longUrl=" .. URI
--JSON = '{"longUrl"="' .. URI .. '"}'
local cjson = require "cjson"
JSON = cjson.encode({longUrl=URI})
ngx.say("JSON\t", JSON)

-- search for "openresty" in google over https:
local res = ngx.location.capture(
"/googleapis/urlshortener/v1/url",
{ method = ngx.HTTP_POST,
body = JSON }
)

if res.status ~= 200 then
ngx.say("failed to query google: ", res.status, ": ", res.body)
return
end

-- here we just forward the Google search result page intact:
ngx.header["Content-Type"] = "application/json; charset=UTF-8"
ngx.say(res.body)

测试成功:
23.239.0.15:10080/=/goo
request_method: POST
args.uri: https://docs.google.com/forms/d/1TBJNar54XKhMu_nRaES5ByPv0078hh0GV0sD5JPCZGU/viewform
uri https://docs.google.com/forms/d/1TBJNar54XKhMu_nRaES5ByPv0078hh0GV0sD5JPCZGU/viewform
JSON {"longUrl":"https:\/\/docs.google.com\/forms\/d\/1TBJNar54XKhMu_nRaES5ByPv0078hh0GV0sD5JPCZGU\/viewform"}
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fiAfLo",
"longUrl": "https://docs.google.com/forms/d/1TBJNar54XKhMu_nRaES5ByPv0078hh0GV0sD5JPCZGU/viewform"
}

so happy now,
俺将合并这个小故事到俺的乱入手册中,
彻底放弃 luacurl 的方案.

thanx for all.

> Regards,
> -agentzh

Yichun Zhang (agentzh)

unread,
Aug 11, 2014, 2:48:02 PM8/11/14
to openresty
Hello!

2014-08-10 22:00 GMT-07:00 Heero Zhang:
> 问个和题目无关的问题,我是通过这个方法访问https的,但一直会报个握手错误,一直没找到为什么,不知道大家是否遇到过?不影响正常使用,只是每次都会报个错。
>
> 2014/08/11 12:55:28 [alert] 5164#0: *4 ignoring stale global SSL error (SSL:

请参见 http://trac.nginx.org/nginx/ticket/476 里的说明。

另外,建议以后遇到错误消息首先 google 之 :)

Regards,
-agentzh

wb du

unread,
Aug 20, 2014, 1:43:19 AM8/20/14
to open...@googlegroups.com
我在使用lua-resty-http时也遇到类似的问题:
在同一台centos上,使用curl “https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET”就可以顺利拿到返回值
但是使用
    local httpc = http.new()
    local res, err = httpc:request_uri(url)
就报错:lua ssl certificate verify error: (20: unable to get local issuer certificate)

不知何故,到目前为止没找到原因。

在 2014年8月10日星期日UTC+8下午10时55分39秒,Zoom Quiet写道:

wd

unread,
Aug 20, 2014, 1:48:00 AM8/20/14
to open...@googlegroups.com
不要在和你问题无关的线索里面提问。


--

wb du

unread,
Aug 20, 2014, 1:49:49 AM8/20/14
to open...@googlegroups.com
改为:httpc:request_uri(url, {ssl_verify=false})后成功。

在 2014年8月20日星期三UTC+8下午1时43分19秒,wb du写道:

Yichun Zhang (agentzh)

unread,
Aug 20, 2014, 8:10:18 PM8/20/14
to openresty
Hello!

2014-08-19 22:43 GMT-07:00 wb du:
> 就报错:lua ssl certificate verify error: (20: unable to get local issuer
> certificate)
>

你需要自己配置你信任的 CA 证书,见

https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate

如果你持有的 CA 证书不是目标证书直接的 CA 的话,你可能同时需要调整 lua_ssl_verify_depth 配置指令的值,比如使用更大的深度。

curl 在 Linux 上经常使用的是 Mozilla 的 NSS 提供的根证书的 bundle. 比如在我的 Fedora 发行版上,以
curl -vv 访问一个 https 站会有如下两行输出:

* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt

出于性能和安全性方面的考虑,你可以有选择地把你真正需要的 CA 根证书从 NSS 导出(或从 web 上取得)成 perm
格式的文件,然后配置成 lua_ssl_trusted_certificate 指向的目标。当然,你也可以把 NSS
里所有的根证书全部导出到一个 .perm 文件,让 nginx 使用。

你可以使用下面这个现成的脚本来实现从 NSS 自动化导出所有的或者你指定搜索词的 CA 证书:

https://github.com/openresty/nginx-devel-utils/blob/master/export-builtin-trusted-certs

由于这些是根证书,所以你需要同时配置 lua_ssl_verify_depth 为较大的值,比如 4 甚至 5.

比如 Google 使用的根 CA 是 Equifax 的,而 verify depth 至少需要置为 3.

网上有一些免费的在线服务可以检查任意指定网站使用的 SSL 证明链,比如

http://www.sslshopper.com/ssl-checker.html

从这个服务,我们可以看到 www.google.com 使用的 SSL 证书的根是 Equifax.

Regards,
-agentzh

wb du

unread,
Aug 28, 2014, 9:45:52 AM8/28/14
to open...@googlegroups.com, openresty
非常感谢。

Mailbox 发送


a8150...@gmail.com

unread,
Jan 5, 2019, 1:08:33 AM1/5/19
to openresty
正好工作中遇到相关问题,谢谢。

在 2014年8月20日星期三 UTC+8下午1:49:49,wb du写道:
Reply all
Reply to author
Forward
0 new messages