]> git.kaiwu.me - nginx.git/commitdiff
Upstream: fixed reinit request with gRPC and Early Hints.
authorSergey Kandaurov <pluknet@nginx.com>
Mon, 23 Jun 2025 10:55:32 +0000 (14:55 +0400)
committerpluknet <pluknet@nginx.com>
Mon, 23 Jun 2025 16:12:21 +0000 (20:12 +0400)
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
src/http/modules/ngx_http_proxy_module.c
src/http/ngx_http_upstream.c
src/http/ngx_http_upstream.h

index d74b1770824fe347e633fa3725a0db7ee952971c..4c95525b46980096013420f778575271ec8199ac 100644 (file)
@@ -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;
 
index ff7460e4461d63ace2f226b44da45dd35e615d66..8d5385c1de3cec42b0703affde11a45f01ceb504 100644 (file)
@@ -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
index d1bcdbbe0104e8251b93f838339e99b2722de360..de0f92a4ff81688e54909bd16d56a4ce0b16f118 100644 (file)
@@ -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));
index 7a47675ebb621f5978a61b7980b44957a3eb165e..f3e9f79799f594eba537c24ece7b4c270fb99ce5 100644 (file)
@@ -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