Reusing TCP sockets while using proxy servers for GET requests

Viewed 17

I am trying to reuse TCP connections while making HTTP requests. Specifically I am trying to reuse TCP sockets I get while making a CONNECT request to proxy servers, but the sockets are destroyed by the time I am trying to reuse them. I am not sure where my implementation is wrong.

Sample code:

private connect(urlString: string, proxy: AxiosProxyConfig)
{
    const url = new URL(urlString), connectStart = Date.now()

    return new Promise<Socket>((resolve, reject) => {
        const req = http.request({
            method: "CONNECT",
            host: proxy.host,
            path: url.host,
            port: proxy.port,
            agent: new http.Agent({
                keepAlive: true,
                keepAliveMsecs: 10,
                timeout: 30000
            }),
            headers: {
                "Connection": "Keep-Alive",
                "Proxy-Authorization": `Basic ${Buffer.from(proxy.auth?.username + ":" + proxy.auth?.password).toString('base64')}`,
            }
        })

        req.on("connect", (_, socket) => {
            this.sockets.set(proxy.host + proxy.port, socket) // save the socket for further reuse
            return resolve(socket)
        })
        
        req.on("error", (e) => {
            return reject(e)
        })

        req.end()
    })
}

private newRequest(urlString: string)
{
    const url = new URL(urlString), proxy = this.proxyStack.get()

    return new Promise(async (resolve, reject) => {
        let socket = this.sockets.get(proxy.host + proxy.port) // try to obtain a socket. whenever I get a socket from this, it is already destroyed (socket.destroyed === true)

        if (!socket) // if a socket is not found, create it first
        {
            socket = await this.connect(urlString, proxy)
        }

        const agent = new https.Agent({ socket })

        https.get({
            host: url.host,
            path: url.href,
            agent,
            headers: {
                "Accept": "application/json",
                "Accept-Encoding": "gzip, deflate, br",
                "User-Agent": "axios/0.27.2",
            }
        }, (res) => {
            if (res.statusCode !== 200)
            {
                return reject(res.statusCode)
            }

            let chunks: Buffer[] = []

            res.on('data', chunk => chunks.push(chunk))
            .on('end', () => {
                resolve(Buffer.concat(chunks).toString())
            })
            .on("error", (e) => {
                return reject(e)
            })
        }).on("error", (e) => {
            return reject(e)
        }).end()
    })
}
0 Answers
Related