0

我正在尝试使用 Lua与Cleverbot API进行交互。我有一个密钥和一个用户名,所以我用 Postman 进行了测试,它运行良好。然后我尝试对 Lua 做同样的事情,但我遇到了一个奇怪的错误。

这是代码:

local https = require("ssl.https")
local string = require("string")
local ltn12 = require ("ltn12")
local funcs = (loadfile "./libs/functions.lua")()

local function cleverbot(msg)
    local params = {
        ['user'] = 'SyR2nvN1cAxxxxxx',
        ['key'] = 'ckym8oDRNvpYO95GmTD14O9PuGxxxxxx',
        ['nick'] = 'cleverbot',
        ['text'] = tostring(msg),
    }

    local body = funcs.encode_table(params)
    local response = {}
    ok, code, headers, status = https.request({
        method = "POST",
        url = "https://cleverbot.io/1.0/ask/",
        headers = {
            ['Accept'] = '*/*',
            ['content-type'] = 'application/x-www-form-urlencoded',
            ['accept-encoding'] = 'gzip',
            ['content-length'] = tostring(#body),
        },
        print(tostring(ok)),
        print(tostring(code)),
        print(tostring(headers)),
        print(tostring(status)),

        source = ltn12.source.string(body),
        sink = ltn12.sink.table(response)
    })

    response = table.concat(response)

    if code ~= 200 then
       return 
    end

    if response[1] ~= nil then
       return tostring(response)
    end
end

但是,当我调用它时,这就是这 4 个打印显示的内容:

nil
tlsv1 alert internal error
nil
nil

我尝试使用 HTTP 进行连接,但这就是发生的情况:

1
301
table: 0xe5f7d60
HTTP/1.1 301 Moved Permanently

response总是空的。请问,我做错了什么?谢谢!

4

1 回答 1

1

我强烈怀疑目标主机(cleverbot.io)坚持通过 SNI(服务器名称指示)获取主机名,而您使用的 ssl-library 不会发送该主机名。通常,服务器会使用默认站点,但当然它们可以自由地让握手失败。似乎这就是 cloudflare(托管或代理cleverbot.io 的地方)所做的。

不幸的是,没有简单的方法可以解决这个问题,除非将底层 ssl 库更改为使用 sni 和 hostnamecleverbot.io 进行 ssl 握手。

也可以看看

Fails:
openssl s_client -connect cleverbot.io:443  -tls1_1 

Succeeds:
openssl s_client -servername cleverbot.io -connect cleverbot.io:443  -tls1_1

这意味着,不仅底层 ssl 库必须支持 sni,而且还必须被告知 lua-binding-layer 使用哪个服务器名。例如,Luasec 目前不使用 sni,afaik

于 2015-12-06T22:30:49.073 回答