如何在路由请求之前在 haproxy 中发送来自 lua 的 https 请求?

how to send https request from lua in haproxy before routing request?

我使用了 haproxy Socket class 作为概述 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

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

同样,经过大量搜索后,我无法找到 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)]"

对于此服务,我在请求中传递域名 header ResolveHost 并在响应中获取 IP header ResolvedIp.

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

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()URL中的域名替换解析的IP

url = string:gsub(domain_name, resolved_ip)

然后使用 http.lua

调用您的 API

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

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