我开发了一个使用libcurl连接到PayPal API的应用程序,我通过OCurl绑定来使用来自Debian服务器上运行的进程的OCaml。代码在Paypal沙箱(端点https://api-3t.sandbox.paypal.com/nvp
)内部始终有效,但在连接到实际的Paypal服务器(端点https://api-3t.paypal.com/nvp
)时永远无效。
Libcurl始终返回CURLE_RECV_ERROR
。普遍的共识是,当出现网络问题时会发生此错误,因此我对此进行了调查。
我使用命令行curl
工具从完全相同的服务器运行完全相同的请求,使用完全相同的进程uid / gid,并且它始终有效。使用tcpdump
跟踪转移并未显示工作命令行curl
和非工作应用程序所做事务结构中的任何重大差异,因此全部显示好像在两种情况下都成功执行了HTTP请求。再说一遍,它是HTTPS,所以我无法确定。
以下是执行请求的OCaml代码:
let c = new Curl.handle in
let buffer = Buffer.create 1763 in
c # set_url "https://api-3t.paypal.com/nvp" ;
c # set_post true ;
c # set_postfields "SOMEDATA" ;
c # set_postfieldsize (String.length "SOMEDATA") ;
c # set_writefunction (fun x -> Buffer.add_string buffer x ; String.length x) ;
c # perform ;
c # cleanup ;
Buffer.contents buffer
以下是等效的curl
命令行:
curl -X POST https://api-3t.paypal.com/nvp -d SOMEDATA
编辑:通过增加libcurl详细程度,我确定了潜在的错误:
GnuTLS recv error (-9): A TLS packet with unexpected length was received.
导致此错误的原因是什么?我该如何调查才能找到答案?
编辑2:命令行和库使用之间的区别似乎是命令行版本链接到OpenSSL,并且库链接到GnuTLS。
如何将两者都链接到OpenSSL?
答案 0 :(得分:1)
首先,进一步调试这些问题的关键是使用curl的调试工具,即VERBOSE设置(以及可能的DEBUGFUNCTION设置,用于以您的方式打印数据)。
c # set_verbose true ;
这将错误识别为GnuTLS的一个问题,也讨论了here,并通过将SSLVERSION设置为3来强制使用SSLv3来解决。
c # set_sslversion 3 ;
答案 1 :(得分:0)
我总是将curl#set_postfieldsize
称为传递给curl#set_postfields
的数据长度。我的代码是:
let make_get url =
let curl = new Curl.handle in
curl#set_writefunction String.length; (* ignore result *)
curl#set_tcpnodelay true;
curl#set_verbose false;
curl#set_post false;
curl#set_url url;
curl
let make_post url =
let curl = make_get url in
curl#set_post true;
curl#set_httpheader [
"Content-Type: text/xml; charset=\"UTF-8\"";
"SOAPAction: \"\"";
];
curl#set_postfields xml;
curl#set_postfieldsize (String.length xml);
curl
我希望这会有所帮助。