如何在HAProxy中路由请求之前从Lua发送https请求?

我使用了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

    -- 设置到服务的请求
    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')

    -- 使用core.tcp获取Socket类的实例
    local socket = core.tcp()
    socket:settimeout(data.timeout)

    -- 连接到服务并发送请求
    if socket:connect(addr, port) then
        if socket:send(req) then
            -- 跳过响应头
            while true do
                local line, _ = socket:receive('*l')

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

            -- 获取响应内容,如果有的话
            local content = socket:receive('*a')
            return content

        else
            core.Alert('无法连接到服务器(发送)')
        end

        socket:close()
    else
        core.Alert('无法连接到服务器(连接)')
    end
end
点赞
用户6587774
用户6587774

最近在解决一个问题时,我发现我们不能传递域名。我正在使用 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-09 08:59:43