Send original headers to the upstream

Kirill A. Korinsky kirill at korins.ky
Tue Jun 25 22:22:14 UTC 2024


Greetings,

Here is a patch that adds a string to proxy_pass_request_headers as a
possible value.

Such a string is used as a prefix for headers which is overwritten by Nginx
when it proxies the request to upstream.

As a nice side effect, this feature preserves the original order of HTTP
headers, which might be needed sometimes.

It is only implemented on the proxy module because there is no other way to
deliver the original request without touching it.

diff --git src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_proxy_module.c
index 536482ec5..6a722042b 100644
--- src/http/modules/ngx_http_proxy_module.c
+++ src/http/modules/ngx_http_proxy_module.c
@@ -117,6 +117,8 @@ typedef struct {
     ngx_uint_t                     headers_hash_max_size;
     ngx_uint_t                     headers_hash_bucket_size;
 
+    ngx_str_t                      request_headers_prefix;
+
 #if (NGX_HTTP_SSL)
     ngx_uint_t                     ssl;
     ngx_uint_t                     ssl_protocols;
@@ -215,6 +217,8 @@ static char *ngx_http_proxy_cookie_flags(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char *ngx_http_proxy_pass_request_headers(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 #if (NGX_HTTP_CACHE)
 static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -445,9 +449,9 @@ static ngx_command_t  ngx_http_proxy_commands[] = {
 
     { ngx_string("proxy_pass_request_headers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
+      ngx_http_proxy_pass_request_headers,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
+      0,
       NULL },
 
     { ngx_string("proxy_pass_request_body"),
@@ -1389,7 +1393,10 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
             if (ngx_hash_find(&headers->hash, header[i].hash,
                               header[i].lowcase_key, header[i].key.len))
             {
-                continue;
+                if (plcf->request_headers_prefix.len == 0) {
+                    continue;
+                }
+                len += plcf->request_headers_prefix.len;
             }
 
             len += header[i].key.len + sizeof(": ") - 1
@@ -1525,7 +1532,12 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
             if (ngx_hash_find(&headers->hash, header[i].hash,
                               header[i].lowcase_key, header[i].key.len))
             {
-                continue;
+                if (plcf->request_headers_prefix.len == 0) {
+                    continue;
+                }
+                b->last = ngx_copy(b->last,
+                                   plcf->request_headers_prefix.data,
+                                   plcf->request_headers_prefix.len);
             }
 
             b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
@@ -3349,6 +3361,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
      *     conf->body_values = NULL;
      *     conf->body_source = { 0, NULL };
      *     conf->redirects = NULL;
+     *     conf->request_headers_prefix = { NULL, 0 };
      *     conf->ssl = 0;
      *     conf->ssl_protocols = 0;
      *     conf->ssl_ciphers = { 0, NULL };
@@ -3727,6 +3740,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
     ngx_conf_merge_value(conf->upstream.intercept_errors,
                               prev->upstream.intercept_errors, 0);
 
+    ngx_conf_merge_str_value(conf->request_headers_prefix,
+                             prev->request_headers_prefix, "");
+
 #if (NGX_HTTP_SSL)
 
     if (ngx_http_proxy_merge_ssl(cf, conf, prev) != NGX_OK) {
@@ -4772,6 +4788,36 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 }
 
 
+static char *
+ngx_http_proxy_pass_request_headers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_proxy_loc_conf_t *plcf = conf;
+
+    ngx_str_t                  *value;
+
+    if (plcf->upstream.pass_request_headers != NGX_CONF_UNSET) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    if (ngx_strcmp(value[1].data, "off") == 0) {
+        plcf->upstream.pass_request_headers = 0;
+        return NGX_CONF_OK;
+    }
+
+    plcf->upstream.store = 1;
+
+    if (ngx_strcmp(value[1].data, "on") == 0) {
+        return NGX_CONF_OK;
+    }
+
+    plcf->request_headers_prefix = value[1];
+
+    return NGX_CONF_OK;
+}
+
+
 #if (NGX_HTTP_CACHE)
 
 static char *

-- 
wbr, Kirill



More information about the nginx mailing list