details:   
https://github.com/nginx/nginx/commit/cdf7a9c6cb7f344efc80d790fbacdc1c94ab16e3
branches:  master
commit:    cdf7a9c6cb7f344efc80d790fbacdc1c94ab16e3
user:      Sergey Kandaurov <pluk...@nginx.com>
date:      Mon, 23 Jun 2025 14:55:32 +0400
description:
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.

---
 src/http/modules/ngx_http_grpc_module.c  | 11 +++++++++++
 src/http/modules/ngx_http_proxy_module.c | 14 +++++++++++---
 src/http/ngx_http_upstream.c             | 10 ++--------
 src/http/ngx_http_upstream.h             |  1 +
 4 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/src/http/modules/ngx_http_grpc_module.c 
b/src/http/modules/ngx_http_grpc_module.c
index d74b17708..4c95525b4 100644
--- a/src/http/modules/ngx_http_grpc_module.c
+++ b/src/http/modules/ngx_http_grpc_module.c
@@ -1928,6 +1928,17 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
                 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;
 
diff --git a/src/http/modules/ngx_http_proxy_module.c 
b/src/http/modules/ngx_http_proxy_module.c
index ff7460e44..8d5385c1d 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1985,8 +1985,18 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
             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 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
              * 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
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index d1bcdbbe0..de0f92a4f 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1123,7 +1123,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, 
ngx_http_upstream_t *u)
         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 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, 
ngx_http_upstream_t *u)
             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 @@ ngx_http_upstream_process_early_hints(ngx_http_request_t 
*r,
         }
     }
 
-    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));
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 7a47675eb..f3e9f7979 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -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
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to