From 8e2ecac95b17cabc13a61a3d91ed99f350412f75 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 11 Nov 2023 23:08:34 +0100 Subject: net.http: Add simple connection pooling This should speed up repeated requests to the same site by keeping their connections around and sending more requests on them. Sending multiple requests at the same time is not supported, instead a request started while another to the same authority is in progress would open a new one and the first one to complete would go back in the pool. This could be investigated in the future. Some http servers limit the number of requests per connection and this is not tested and could cause one request to fail, but hopefully it will close the connection and prevent it from being reused. --- net/http.lua | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/net/http.lua b/net/http.lua index 07c7d41f..2685b491 100644 --- a/net/http.lua +++ b/net/http.lua @@ -51,10 +51,19 @@ local function log_if_failed(req, ret, ...) return ...; end -local function destroy_request(request) +local function destroy_request(request, force) local conn = request.conn; if conn then request.conn = nil; + local pool = request.http.pool; + if pool and not force then + local pool_id = request.scheme .. "://" .. request.authority; + if not pool[pool_id] then + pool[conn] = pool_id; + pool[pool_id] = conn; + return; + end + end conn:close() end end @@ -193,6 +202,13 @@ function listener.ondisconnect(conn, err) if request and request.conn then request:reader(nil, err or "closed"); end + if request and request.http.pool then + local pool = request.http.pool; + local pool_id = pool[conn]; + if pool_id then + pool[pool_id], pool[conn] = nil, nil; + end + end requests[conn] = nil; end @@ -296,6 +312,23 @@ local function request(self, u, ex, callback) end end + if self.pool then + local pool_id = req.scheme .. "://" .. req.authority; + local conn = self.pool[pool_id]; + if conn then + log("debug", "Re-using connection to %s from pool", req.host); + self.pool[pool_id] = nil; + self.pool[conn] = nil; + req.conn = conn; + requests[conn] = req; + self.events.fire_event("request", { http = self, request = req, url = u }); + listener.onconnect(conn); + return req; + else + log("debug", "Opening a new connection for this request"); + end + end + local http_service = basic_resolver.new(host, port_number, "tcp", { servername = req.host; use_dane = use_dane }); connect(http_service, listener, { sslctx = sslctx }, req); @@ -332,6 +365,10 @@ local function new(options) end or new; events = events.new(); }; + if options and options.connection_pooling then + -- util.cache in the future? + http.pool = {}; + end return http; end -- cgit v1.2.3