changeset 9422:44a05528fa46

Upstream: fixed reinit request with gRPC and Early Hints. The gRPC module context has connection specific state, which can be lost after request reinitialization when it comes to processing early hints. The fix is to do only a portion of u->reinit_request() implementation required after processing early hints, now inlined in modules. Now NGX_HTTP_UPSTREAM_EARLY_HINTS is returned from u->process_header() for early hints. When reading a cached response, this code is mapped to NGX_HTTP_UPSTREAM_INVALID_HEADER to indicate invalid header format.
author Sergey Kandaurov <pluknet@nginx.com>
date Mon, 23 Jun 2025 14:55:32 +0400
parents 927f43435c0a
children f235f401cefc
files src/http/modules/ngx_http_grpc_module.c src/http/modules/ngx_http_proxy_module.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h
diffstat 4 files changed, 25 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_grpc_module.c	Wed May 21 22:30:20 2025 +0100
+++ b/src/http/modules/ngx_http_grpc_module.c	Mon Jun 23 14:55:32 2025 +0400
@@ -1928,6 +1928,17 @@
                 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "grpc header done");
 
+                if (u->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
+                    if (ctx->end_stream) {
+                        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                                      "upstream prematurely closed stream");
+                        return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+                    }
+
+                    ctx->status = 0;
+                    return NGX_HTTP_UPSTREAM_EARLY_HINTS;
+                }
+
                 if (ctx->end_stream) {
                     u->headers_in.content_length_n = 0;
 
--- a/src/http/modules/ngx_http_proxy_module.c	Wed May 21 22:30:20 2025 +0100
+++ b/src/http/modules/ngx_http_proxy_module.c	Mon Jun 23 14:55:32 2025 +0400
@@ -1985,8 +1985,18 @@
             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                            "http proxy header done");
 
+            ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
             if (r->upstream->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
-                return NGX_OK;
+                ctx->status.code = 0;
+                ctx->status.count = 0;
+                ctx->status.start = NULL;
+                ctx->status.end = NULL;
+
+                r->upstream->process_header =
+                                            ngx_http_proxy_process_status_line;
+                r->state = 0;
+                return NGX_HTTP_UPSTREAM_EARLY_HINTS;
             }
 
             /*
@@ -2036,8 +2046,6 @@
              * connections alive in case of r->header_only or X-Accel-Redirect
              */
 
-            ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
             if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
                 || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
                 || ctx->head
--- a/src/http/ngx_http_upstream.c	Wed May 21 22:30:20 2025 +0100
+++ b/src/http/ngx_http_upstream.c	Mon Jun 23 14:55:32 2025 +0400
@@ -1123,7 +1123,7 @@
         return NGX_ERROR;
     }
 
-    if (rc == NGX_AGAIN) {
+    if (rc == NGX_AGAIN || rc == NGX_HTTP_UPSTREAM_EARLY_HINTS) {
         rc = NGX_HTTP_UPSTREAM_INVALID_HEADER;
     }
 
@@ -2533,9 +2533,7 @@
             continue;
         }
 
-        if (rc == NGX_OK
-            && u->headers_in.status_n == NGX_HTTP_EARLY_HINTS)
-        {
+        if (rc == NGX_HTTP_UPSTREAM_EARLY_HINTS) {
             rc = ngx_http_upstream_process_early_hints(r, u);
 
             if (rc == NGX_OK) {
@@ -2651,10 +2649,6 @@
         }
     }
 
-    if (u->reinit_request(r) != NGX_OK) {
-        return NGX_ERROR;
-    }
-
     ngx_http_clean_header(r);
 
     ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
--- a/src/http/ngx_http_upstream.h	Wed May 21 22:30:20 2025 +0100
+++ b/src/http/ngx_http_upstream.h	Mon Jun 23 14:55:32 2025 +0400
@@ -43,6 +43,7 @@
                                              |NGX_HTTP_UPSTREAM_FT_HTTP_429)
 
 #define NGX_HTTP_UPSTREAM_INVALID_HEADER     40
+#define NGX_HTTP_UPSTREAM_EARLY_HINTS        41
 
 
 #define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT    0x00000002