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) が、使用する ssl-library が送信しない SNI (サーバー名表示) を介してホスト名を取得することを主張していることです。通常、サーバーはデフォルトのサイトを使用しますが、もちろん、ハンドシェイクを失敗させてもかまいません。これは、cloudflare (cleverbot.io がホストまたはプロキシされている場所) が行うことのようです。

残念ながら、これを修正する簡単な方法はありません。基盤となる ssl-libraries を変更して、ssl ハンドシェークにホスト名がcleverbot.io の sni を使用するように変更する必要があります。

こちらもご覧ください

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 を利用していません。

于 2015-12-06T22:30:49.073 に答える