Send original headers to the upstream

Kirill A. Korinsky kirill at korins.ky
Fri Jun 28 00:03:13 UTC 2024


Greetings,

Retesting the patch requires some time.

On Wed, 26 Jun 2024 02:42:01 +0100,
Maxim Dounin <mdounin at mdounin.ru> wrote:
>
> Note that as implemented, you won't be able to distinguish
> original requests headers from the ones with prefix added.  E.g.,
> assuming prefix "X-Original-", and original request headers:
>
> Host: foo
> X-Original-Host: bar
>
> you'll get
>
> X-Original-Host: foo
> X-Original-Host: bar
>
> in the upstream request, and you won't be able to tell which one
> is real.
>
> Following the exiting proxy_set_header behaviour, I would rather
> suggests that such a feature, if implemented, should drop all the
> headers with the configured prefix.
>
[...]
> 
> Not sure if reusing "proxy_pass_request_headers" for such a
> feature is a good idea.  From the behaviour of
> "proxy_pass_request_headers off;", I would rather assume that
> "proxy_pass_request_headers X-Original-;" will pass all the
> headers with the specified prefix, and not just the headers which
> were modified.
>

I agree that design when "proxy_pass_request_headers X-Original-;" simple
maps all original headers into X-Original-BlaBla is cleaner. It also allows
to avoid need to drop any header as well.

So, here the updated patch which address all minor remarks as well:

https://freenginx.org/pipermail/nginx/2024-June/000238.html

diff --git src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_proxy_module.c
index 536482ec5..7622360d2 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"),
@@ -1386,9 +1390,11 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
                 i = 0;
             }
 
-            if (ngx_hash_find(&headers->hash, header[i].hash,
-                              header[i].lowcase_key, header[i].key.len))
-            {
+            if (plcf->request_headers_prefix.len > 0) {
+                len += plcf->request_headers_prefix.len;
+            } else if (ngx_hash_find(&headers->hash, header[i].hash,
+                                     header[i].lowcase_key,
+                                     header[i].key.len)) {
                 continue;
             }
 
@@ -1522,9 +1528,13 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
                 i = 0;
             }
 
-            if (ngx_hash_find(&headers->hash, header[i].hash,
-                              header[i].lowcase_key, header[i].key.len))
-            {
+            if (plcf->request_headers_prefix.len > 0) {
+                b->last = ngx_copy(b->last,
+                                   plcf->request_headers_prefix.data,
+                                   plcf->request_headers_prefix.len);
+            } else if (ngx_hash_find(&headers->hash, header[i].hash,
+                                     header[i].lowcase_key,
+                                     header[i].key.len)) {
                 continue;
             }
 
@@ -3349,6 +3359,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 +3738,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 +4786,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.pass_request_headers = 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