0

我使用这里概述的 haproxy Socket 类https://www.haproxy.com/blog/5-ways-to-extend-haproxy-with-lua/#actions从 lua 代码向外部服务发出http请求(参见下面的代码)。

  1. 如何向服务发出https请求?
  2. 是否可以指定域名而不是要连接的服务的 IP 地址?

任何帮助表示赞赏。

local function http_request(txn, data)
    local addr = <external-IP>
    local port = 80

    -- Set up a request to the service
    local hdrs = {
        [1] = string.format('host: %s:%s', addr, port),
        [2] = 'accept: */*',
        [3] = 'connection: close'
    }
    
    local req = {
        [1] = string.format('GET %s HTTP/1.1', data.path),
        [2] = table.concat(hdrs, '\r\n'),
        [3] = '\r\n'
    }

    req = table.concat(req,  '\r\n')

    -- Use core.tcp to get an instance of the Socket class
    local socket = core.tcp()
    socket:settimeout(data.timeout)

    -- Connect to the service and send the request
    if socket:connect(addr, port) then
        if socket:send(req) then
            -- Skip response headers
            while true do
                local line, _ = socket:receive('*l')

                if not line then break end
                if line == '' then break end
            end

            -- Get response body, if any
            local content = socket:receive('*a')
            return content

        else
            core.Alert('Could not connect to server (send)')
        end

        socket:close()
    else
        core.Alert('Could not connect to server (connect)')
    end
end
4

1 回答 1

1

最近在处理一个问题时,我发现我们无法传递域名。我正在使用http.lua库。这个 http.lua 库使用 Socket 类,就像您在代码中所做的那样。

同样经过大量搜索后,我无法找到 dns 解析器库。一个是与 nginx lua 相关的东西,但它需要安装许多不同的 lua 库,所以我跳过了它。

我所做的工作是,在 HAProxy 中创建了我自己的 dns 解析器服务http://127.0.0.1:53535 ,如下所示

listen lua_dns
    bind 127.0.0.1:53535

    http-request do-resolve(txn.dstip,mydns,ipv4) hdr(ResolveHost),lower
    http-request return status 200 content-type text/plain lf-string OK hdr ResolvedIp "%[var(txn.dstip)]"

为此服务,我在请求标头中传递域名ResolveHost并在响应标头中获取 IP ResolvedIp

现在从 URL 解析域并调用 dns 解析器服务的 lua 函数如下

local function parse_domain(url)

    local schema, host, _ = url:match("^(.*)://(.-)[?/](.*)$")

    if not schema then
        -- maybe path (request uri) is missing
        schema, host = url:match("^(.*)://(.-)$")
        if not schema then
            core.Info("ERROR :: Could not parse URL: "..url)
            return nil
        end
    end

    return host

end

local function resolve_domain(domain)

    local d = parse_domain(domain)    
    
    local r, msg = http.get{ url = "http://127.0.0.1:53535", headers={ResolveHost=d} }
    if r == nil then
        core.Info("ERROR: "..msg..". While resolving doamin: "..d)
        return msg
    end

    return r.headers['resolvedip']

end

现在使用 gsub() 将解析的 IP 替换为 URL 中的域名

url = string:gsub(domain_name, resolved_ip)

然后使用 http.lua 调用你的 API

local res, msg = http.get{ url=url, headers=headers }

这里 http.lua 库将处理 HTTP 和 HTTPS url。

于 2021-09-09T08:59:43.293 回答