]> git.kaiwu.me - nginx.git/commitdiff
HTTP/2: merge upstream Priority header for proxied requests
authorAndrew Clayton <a.clayton@nginx.com>
Tue, 22 Sep 2026 00:53:10 +0000 (01:53 +0100)
committerAndrew Clayton <a.clayton@nginx.com>
Mon, 28 Sep 2026 21:01:20 +0000 (22:01 +0100)
When nginx proxies a request over HTTP/2 and the upstream returns a
Priority response header, record it as the stream's server priority and
recompute the effective priority by merging it with the client's value
(RFC 9218, Section 8): a parameter present in the response overrides the
client's, a parameter absent leaves it unchanged.  The client and server
inputs are kept separate so a later client PRIORITY_UPDATE does not
discard the server hint.

The merge affects only how this hop schedules the stream; the Priority
header forwarded to the client is left unchanged, so
$upstream_http_priority continues to report what the origin sent.

Assisted-by: opencode:claude-opus-4.8
src/http/ngx_http_upstream.c

index 3f865345ba7a86826d392da1ae43924c5e0e6985..6f328e6a4238929e687a3182458aa134de8c0aa1 100644 (file)
@@ -139,6 +139,8 @@ static ngx_int_t
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_process_priority(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset);
 static ngx_int_t
@@ -336,6 +338,10 @@ static ngx_http_upstream_header_t  ngx_http_upstream_headers_in[] = {
                  ngx_http_upstream_copy_header_line,
                  offsetof(ngx_http_headers_out_t, content_encoding), 0 },
 
+    { ngx_string("Priority"),
+                 ngx_http_upstream_process_priority, 0,
+                 ngx_http_upstream_copy_header_line, 0, 0 },
+
     { ngx_null_string, NULL, 0, NULL, 0, 0 }
 };
 
@@ -5594,6 +5600,45 @@ ngx_http_upstream_process_vary(ngx_http_request_t *r,
 }
 
 
+static ngx_int_t
+ngx_http_upstream_process_priority(ngx_http_request_t *r,
+    ngx_table_elt_t *h, ngx_uint_t offset)
+{
+#if (NGX_HTTP_V2)
+    ngx_http_priority_t    priority;
+    ngx_http_v2_stream_t  *stream;
+
+    if (r != r->main) {
+        return NGX_OK;
+    }
+
+    /* RFC 9218, Section 8: server hints override the client's values */
+
+    stream = r->stream;
+
+    if (stream == NULL) {
+        return NGX_OK;
+    }
+
+    if (ngx_http_priority_parse(&h->value, &priority) != NGX_OK
+        || !(priority.urgency_set || priority.incremental_set))
+    {
+        return NGX_OK;
+    }
+
+    stream->priority.server = priority;
+    ngx_http_priority_state_update(&stream->priority);
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http upstream priority: u=%ud i=%ud",
+                   stream->priority.effective.urgency,
+                   stream->priority.effective.incremental);
+#endif
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)