Comparison

net/http.lua @ 13319:6d6291dfe735

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.
author Kim Alvefur <zash@zash.se>
date Sat, 11 Nov 2023 23:08:34 +0100
parent 12974:ba409c67353b
child 13320:23f95714c386
comparison
equal deleted inserted replaced
13318:4a437dd62cc9 13319:6d6291dfe735
49 end 49 end
50 end 50 end
51 return ...; 51 return ...;
52 end 52 end
53 53
54 local function destroy_request(request) 54 local function destroy_request(request, force)
55 local conn = request.conn; 55 local conn = request.conn;
56 if conn then 56 if conn then
57 request.conn = nil; 57 request.conn = nil;
58 local pool = request.http.pool;
59 if pool and not force then
60 local pool_id = request.scheme .. "://" .. request.authority;
61 if not pool[pool_id] then
62 pool[conn] = pool_id;
63 pool[pool_id] = conn;
64 return;
65 end
66 end
58 conn:close() 67 conn:close()
59 end 68 end
60 end 69 end
61 70
62 local function cancel_request(request, reason) 71 local function cancel_request(request, reason)
191 function listener.ondisconnect(conn, err) 200 function listener.ondisconnect(conn, err)
192 local request = requests[conn]; 201 local request = requests[conn];
193 if request and request.conn then 202 if request and request.conn then
194 request:reader(nil, err or "closed"); 203 request:reader(nil, err or "closed");
195 end 204 end
205 if request and request.http.pool then
206 local pool = request.http.pool;
207 local pool_id = pool[conn];
208 if pool_id then
209 pool[pool_id], pool[conn] = nil, nil;
210 end
211 end
196 requests[conn] = nil; 212 requests[conn] = nil;
197 end 213 end
198 214
199 function listener.onattach(conn, req) 215 function listener.onattach(conn, req)
200 requests[conn] = req; 216 requests[conn] = req;
291 local sslctx = false; 307 local sslctx = false;
292 if using_https then 308 if using_https then
293 sslctx = ex and ex.sslctx or self.options and self.options.sslctx; 309 sslctx = ex and ex.sslctx or self.options and self.options.sslctx;
294 if ex and ex.use_dane ~= nil then 310 if ex and ex.use_dane ~= nil then
295 use_dane = ex.use_dane; 311 use_dane = ex.use_dane;
312 end
313 end
314
315 if self.pool then
316 local pool_id = req.scheme .. "://" .. req.authority;
317 local conn = self.pool[pool_id];
318 if conn then
319 log("debug", "Re-using connection to %s from pool", req.host);
320 self.pool[pool_id] = nil;
321 self.pool[conn] = nil;
322 req.conn = conn;
323 requests[conn] = req;
324 self.events.fire_event("request", { http = self, request = req, url = u });
325 listener.onconnect(conn);
326 return req;
327 else
328 log("debug", "Opening a new connection for this request");
296 end 329 end
297 end 330 end
298 331
299 local http_service = basic_resolver.new(host, port_number, "tcp", { servername = req.host; use_dane = use_dane }); 332 local http_service = basic_resolver.new(host, port_number, "tcp", { servername = req.host; use_dane = use_dane });
300 connect(http_service, listener, { sslctx = sslctx }, req); 333 connect(http_service, listener, { sslctx = sslctx }, req);
330 end 363 end
331 return new(final_options); 364 return new(final_options);
332 end or new; 365 end or new;
333 events = events.new(); 366 events = events.new();
334 }; 367 };
368 if options and options.connection_pooling then
369 -- util.cache in the future?
370 http.pool = {};
371 end
335 return http; 372 return http;
336 end 373 end
337 374
338 local default_http = new({ 375 local default_http = new({
339 sslctx = { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" }, alpn = "http/1.1", verify = "peer" }; 376 sslctx = { mode = "client", protocol = "sslv23", options = { "no_sslv2", "no_sslv3" }, alpn = "http/1.1", verify = "peer" };