]> git.kaiwu.me - njs.git/commitdiff
Fetch: check keepalive connections before reuse
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 29 May 2026 23:38:04 +0000 (16:38 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Mon, 1 Jun 2026 15:44:59 +0000 (08:44 -0700)
nginx/ngx_js_http.c

index 2df784fe2711f8926b8817f3b301d8164decea9f..3f9355dd7ec3cbc101a8efb4c4057b6c784b08ee 100644 (file)
@@ -35,6 +35,7 @@ static void ngx_js_http_dummy_handler(ngx_event_t *ev);
 static void ngx_js_http_keepalive_close_handler(ngx_event_t *ev);
 static void ngx_js_http_keepalive_dummy_handler(ngx_event_t *ev);
 
+static ngx_int_t ngx_js_http_keepalive_check_connection(ngx_connection_t *c);
 static ngx_int_t ngx_js_http_get_keepalive_connection(ngx_js_http_t *http);
 static ngx_int_t ngx_js_http_free_keepalive_connection(ngx_js_http_t *http);
 
@@ -1812,7 +1813,7 @@ static ngx_int_t
 ngx_js_http_get_keepalive_connection(ngx_js_http_t *http)
 {
     ngx_str_t                      *host;
-    ngx_queue_t                    *q;
+    ngx_queue_t                    *q, *next;
     ngx_connection_t               *c;
     ngx_js_loc_conf_t              *conf;
     ngx_js_http_keepalive_cache_t  *cache;
@@ -1827,8 +1828,9 @@ ngx_js_http_get_keepalive_connection(ngx_js_http_t *http)
 
     for (q = ngx_queue_head(&conf->fetch_keepalive_cache);
          q != ngx_queue_sentinel(&conf->fetch_keepalive_cache);
-         q = ngx_queue_next(q))
+         q = next)
     {
+        next = ngx_queue_next(q);
         cache = ngx_queue_data(q, ngx_js_http_keepalive_cache_t, queue);
 
         if (host->len != cache->host_len) {
@@ -1850,6 +1852,19 @@ ngx_js_http_get_keepalive_connection(ngx_js_http_t *http)
         }
 
         c = cache->connection;
+
+        if (ngx_js_http_keepalive_check_connection(c) != NGX_OK) {
+            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, http->log, 0,
+                           "js http keepalive closing cached connection: %d",
+                           c->fd);
+
+            ngx_queue_remove(q);
+            ngx_js_http_close_connection(c);
+            ngx_queue_insert_head(&conf->fetch_keepalive_free, q);
+
+            continue;
+        }
+
         ngx_queue_remove(q);
         ngx_queue_insert_head(&conf->fetch_keepalive_free, q);
 
@@ -1883,6 +1898,32 @@ found:
 }
 
 
+static ngx_int_t
+ngx_js_http_keepalive_check_connection(ngx_connection_t *c)
+{
+    ssize_t  n;
+    u_char   buf[1];
+
+    if (c->close || c->read->timedout) {
+        return NGX_DECLINED;
+    }
+
+    n = recv(c->fd, buf, 1, MSG_PEEK);
+
+    if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
+        c->read->ready = 0;
+
+        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
+            return NGX_ERROR;
+        }
+
+        return NGX_OK;
+    }
+
+    return NGX_DECLINED;
+}
+
+
 static ngx_int_t
 ngx_js_http_free_keepalive_connection(ngx_js_http_t *http)
 {
@@ -2012,35 +2053,19 @@ ngx_js_http_keepalive_dummy_handler(ngx_event_t *ev)
 static void
 ngx_js_http_keepalive_close_handler(ngx_event_t *ev)
 {
-    ssize_t                         n;
     ngx_connection_t               *c;
     ngx_js_loc_conf_t              *conf;
     ngx_js_http_keepalive_cache_t  *cache;
-    u_char                          buf[1];
 
     c = ev->data;
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    "js http keepalive close handler: %d", c->fd);
 
-    if (c->close || ev->timedout) {
-        goto close;
-    }
-
-    n = recv(c->fd, buf, 1, MSG_PEEK);
-
-    if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
-        ev->ready = 0;
-
-        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
-            goto close;
-        }
-
+    if (ngx_js_http_keepalive_check_connection(c) == NGX_OK) {
         return;
     }
 
-close:
-
     cache = c->data;
     conf = cache->conf;