]> git.kaiwu.me - nginx.git/commitdiff
Proxy: fixed HTTP/2 upstream with caching enabled.
authorRoman Arutyunyan <arut@nginx.com>
Wed, 11 Feb 2026 12:29:37 +0000 (12:29 +0000)
committerRoman Arutyunyan <arutyunyan.roman@gmail.com>
Wed, 11 Feb 2026 14:57:43 +0000 (18:57 +0400)
Previously, when proxy_cache and keepalive were both enabled with an
HTTP/2 upstream, the second request for a cached resource could fail with
"upstream sent frame for unknown stream" error followed by "cache file
contains invalid header".

This happened because ctx->id was set to 1 in the case when no upstream
connection exists (e.g. cache hit), making the stream id check fail when
the cached response contained frames from a different stream.

The fix is to set ctx->id to 0 when there is no upstream connection,
indicating that no real stream exists, and skip the stream id validation
in this case.  Also, ctx->id = 1 is now set only for new connections,
not in the shared done label.

Closes: https://github.com/nginx/nginx/issues/1101
src/http/modules/ngx_http_proxy_v2_module.c

index f109fe94e7c239a60921d55f01c51b0a1cf49fce..2c8a3d4d1c2efb64fccb15f362c12a3251135ff3 100644 (file)
@@ -1395,7 +1395,7 @@ ngx_http_proxy_v2_process_header(ngx_http_request_t *r)
                 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
             }
 
-            if (ctx->stream_id && ctx->stream_id != ctx->id) {
+            if (ctx->id && ctx->stream_id && ctx->stream_id != ctx->id) {
                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                               "upstream sent frame for unknown stream %ui",
                               ctx->stream_id);
@@ -4076,6 +4076,8 @@ ngx_http_proxy_v2_get_connection_data(ngx_http_request_t *r,
             return NGX_ERROR;
         }
 
+        ctx->id = 0;
+
         goto done;
     }
 
@@ -4117,6 +4119,8 @@ ngx_http_proxy_v2_get_connection_data(ngx_http_request_t *r,
     cln->handler = ngx_http_proxy_v2_cleanup;
     ctx->connection = cln->data;
 
+    ctx->id = 1;
+
 done:
 
     ctx->connection->init_window = NGX_HTTP_V2_DEFAULT_WINDOW;
@@ -4126,7 +4130,6 @@ done:
     ctx->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
     ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;
 
-    ctx->id = 1;
     ctx->connection->last_stream_id = 1;
 
     return NGX_OK;