# $upstream\_http\_NAME and $sent\_http\_NAME vars not available in certain scopes

**URL:** <https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381>\
**Category:** NGINX\
**Created:** [March 30, 2016, 1:13pm UTC](https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381 "2016-03-30T13:13:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rafa\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/958977/32.png) [@Rafa\_F](https://www.ruby-forum.com/u/Rafa_F)\
**Post date:** [March 30, 2016, 1:13pm UTC](https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381/1 "2016-03-30T13:13:44Z")

</div>

Hi all

I am developing a proxy service which uses NGINX to reverse proxy, kind  
of  
CDN-like but very specific to our needs. During this. I have hit an  
issue  
which I _think_ is a bug but wanted to ask in case anyone can point to a  
solution or some reading I can do. The problem I have is this:

$upstream\_http\_NAME and $sent\_http\_NAME variables seem to be  
unpopulated/blank at some points in my config when other embedded  
variables  
_are_ populated. This is probably best illustrated via an example, so  
here’s  
a simplified test case I created:

user nginx;  
worker\_processes auto;  
worker\_priority -15;  
worker\_rlimit\_nofile 50000;

events {  
# worker\_connections benefits from a large value in that it reduces  
error counts  
worker\_connections 20000;  
multi\_accept on;  
}

http {

# for dynamic upstreams

resolver 8.8.8.8;

# Default includes

include /etc/nginx/current/mime.types;  
default\_type application/octet-stream;  
include /etc/nginx/current/proxy.conf;

# Tuning options - these are mainly quite GTM-specific

server\_tokens off;  
keepalive\_requests 1024;  
keepalive\_timeout 120s 120s;  
sendfile on;  
tcp\_nodelay on;  
tcp\_nopush on;  
client\_header\_timeout 5s;  
open\_file\_cache max=16384 inactive=600s;  
open\_file\_cache\_valid 600s;  
open\_file\_cache\_min\_uses 0;  
open\_file\_cache\_errors on;  
output\_buffers 64 128k;

# NEW - AIO

aio on;  
directio 512;

# For small files and heavy load, this gives ~5-6x greater throughput

(avoids swamping workers with one request)  
postpone\_output 0;  
reset\_timedout\_connection on;  
send\_timeout 3s;  
sendfile\_max\_chunk 1m;  
large\_client\_header\_buffers 8 8k;  
connection\_pool\_size 4096;

# client\_body\_buffer\_size - Sets buffer size for reading client

request  
body. In case the request body is larger than the buffer, the whole body  
or  
only its part is written to a temporary file  
client\_body\_buffer\_size 8k;  
client\_header\_buffer\_size 8k;

# client\_max\_body\_size - Sets the maximum allowed size of the client

request body, specified in the “Content-Length” request header field. If  
the  
size in a request exceeds the configured value, the 413 (Request Entity  
Too  
Large) error is returned to the client  
client\_max\_body\_size 8m;

# We need to increase the hash bucket size as the R53 names are long!

server\_names\_hash\_bucket\_size 128;

# Same for proxy\_headers\_hash\_max\_size and

proxy\_headers\_hash\_bucket\_size  
proxy\_headers\_hash\_max\_size 4096;  
proxy\_headers\_hash\_bucket\_size 1024;

# Logging

# NOTE: $host may need to in fact be $hostname

log\_format standard ‘“$remote\_addr” “$time\_iso8601” “$request\_method”  
“$scheme” “$host” “$request\_uri” “$server\_protocol” “$status”  
“$bytes\_sent”  
“$http\_referer” “$http\_user\_agent” “$ssl\_protocol” “$ssl\_cipher”  
“$ssl\_server\_name” “$ssl\_session\_reused”’;  
access\_log /var/log/nginx/main-access.log standard;  
error\_log /var/log/nginx/main-error.log warn;

recursive\_error\_pages on;

# GeoIP config

# This appears to need an absolute path, despite the docs suggesting

it  
doesn’t.

# Path is defined in bake script so changes to that will break this

# geoip\_country /usr/local/GeoIP.dat;

geoip\_city /var/lib/GeoIP/GeoLiteCity.dat;  
#geoip\_proxy 0.0.0.0/0;  
#geoip\_proxy\_recursive on;

# Proxy global configuration

# NOTES:

# proxy\_cache\_path is an http scope (global) directive

# keys\_zone=shared\_cache:XXXXm; denotes the amount of RAM to allow for

cache index, 1MB ~7k-8k cached objects - exceeding the number of cached  
objects possible due to index size results in LRU invocation  
proxy\_cache\_path /mnt/gtm\_cache\_data levels=1:2 use\_temp\_path=on  
keys\_zone=shared\_cache:256m inactive=1440m;  
proxy\_temp\_path /mnt/gtm\_cache\_temp;

# NGINX recommends HTTP 1.1 for keepalive, proxied conns. (which we

use)  
proxy\_http\_version 1.1;

# NGINX recommends clearing the connection request header for

keepalive  
http 1.1 conns  
proxy\_set\_header Connection “”;

# Conditions under which we want to try then next (if there is one)

upstream server in the list & timeouts  
proxy\_next\_upstream error timeout invalid\_header http\_500 http\_502  
http\_503  
http\_504;  
proxy\_next\_upstream\_timeout 5s;  
proxy\_next\_upstream\_tries 3;

ssl\_session\_cache shared:global\_ssl\_cache:128m;

ssl\_session\_timeout 120m;  
ssl\_session\_tickets on;  
#ssl\_session\_ticket\_key /etc/nginx/current/tls/session/tkt.key;

# TEST CASE:

# Set up a DNS or hosts file entry to point to your NGINX instance

running  
this config

# Hit this with URL:

https:///response-headers?Content-Type=text%2Fplain%3B+charset%3DUTF-8&via=1.1%20httpbin3&tester=hello

# To try to check if we can work around the problem below (vars not

existing (?) at time of use/need), we’ll try to copy the var via a map  
map $upstream\_http\_via $copy\_map\_upstream\_http\_via {  
default $upstream\_http\_via;  
}

upstream origin {  
server [httpbin.org:443](http://httpbin.org:443) resolve;  
}

# Generic/common server for listen port configs

server {

```
# TMP removing fastopen=None backlog=-1 as the directives don't 

```

work!  
listen \*:80 so\_keepalive=120s:30s:20 default\_server;  
listen \*:443 ssl http2 reuseport deferred so\_keepalive=120s:30s:20  
default\_server;

```
# This cert & key will never actually be used but are needed to 

```

allow the  
:443 operation - without them the connection will be closed  
ssl\_certificate /etc/nginx/current/tls/certs/default.crt;  
ssl\_certificate\_key /etc/nginx/current/tls/private/default.key;

```
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

location / {

  # To try to check if we can work around the problem below (vars 

```

not  
existing (?) at time of use/need), we’ll try to copy the var via a set  
set $copy\_set\_upstream\_http\_via $upstream\_http\_via;

```
  more_set_headers "SENT_HTTP_VIA: $sent_http_via";
  more_set_headers "HTTP_VIA: $http_via";
  more_set_headers "UPSTREAM_HTTP_VIA: $upstream_http_via";

  # For ref, the upstream is sending e.g. "via: 1.1 string"

  # Problem: These do not match, $upstream_http_via appears not to 

```

be  
populated at this point

# if ( $sent\_http\_via ~\* “^[0-9].[0-9]\ .+$” ) {

# if ($upstream\_http\_via ~\* “^[0-9].[0-9]\ .+”) {

# if ($sent\_http\_via ~\* “^[0-9].[0-9]\ .+”) {

# if ($upstream\_http\_via) {

```
  # This does match - for obvious reasons
  if ($upstream_http_via ~* ".*") {

  # Problem: $upstream_http_via appears not to be populated at this

```

point…  
set $via\_comp “$upstream\_http\_via 1.y BLAH”;  
more\_set\_headers “IF\_VIA\_COMP: Value is $via\_comp”;

```
    # Just to demo the string concat - we'll use a different 

```

embedded var  
set $test\_comp “$ssl\_protocol BLAH”;  
more\_set\_headers “IF\_TEST\_COMP: Value  
is  
$test\_comp”;

```
    # Does the map-copied var exist?
    set $via_comp_copy_map "$copy_map_upstream_http_via 1.y BLAH";
                            more_set_headers "IF_VIA_COMP_COPY_MAP:

```

Value is $via\_comp\_copy\_map";

```
    # Does the set-copied var exist?
    set $via_comp_copy_set "$copy_set_upstream_http_via 1.y BLAH";
                            more_set_headers "IF_VIA_COMP_COPY_SET:

```

Value is $via\_comp\_copy\_set";

```
    # Does a different $upstream_http_X var work? - NO
    set $alt_comp "$upstream_http_tester 1.y BLAH";
                            more_set_headers "IF_ALT_COMP: Value is

```

$alt\_comp";

```
  # ...but $upstream_http_via IS populated at this point
    more_set_headers "UPSTREAM_HTTP_VIA_IF: $upstream_http_via";
    more_set_headers "HTTP_VIA_IF: $http_via";
    more_set_headers "SENT_HTTP_VIA_IF: $sent_http_via";
  }

  proxy_pass https://origin;
}

```

# END TEST CASE

}  
}

(Sorry, couldn’t figure out how to markup the config)

The response headers from a request to this NGIX instance is e.g.:

access-control-allow-credentials:true  
access-control-allow-origin:\*  
content-length:161  
content-type:text/plain; charset=UTF-8  
date:Wed, 30 Mar 2016 10:31:55 GMT  
if\_alt\_comp:Value is 1.y BLAH  
if\_test\_comp:Value is TLSv1.2 BLAH  
if\_via\_comp:Value is 1.y BLAH  
if\_via\_comp\_copy\_map:Value is 1.y BLAH  
if\_via\_comp\_copy\_set:Value is 1.y BLAH  
sent\_http\_via:1.1 httpbin3  
sent\_http\_via\_if:1.1 httpbin3  
server:nginx  
status:200  
tester:hello  
upstream\_http\_via:1.1 httpbin3  
upstream\_http\_via\_if:1.1 httpbin3  
via:1.1 httpbin3

So you can see from the section:  
if\_alt\_comp:Value is 1.y BLAH  
if\_test\_comp:Value is TLSv1.2 BLAH  
if\_via\_comp:Value is 1.y BLAH  
if\_via\_comp\_copy\_map:Value is 1.y BLAH  
if\_via\_comp\_copy\_set:Value is 1.y BLAH

That there’s a blank space where the value from $upstream\_http\_via or  
$sent\_http\_via should be.

So my questions are:  
Can anyone see something I have done wrong?  
Is this expected behaviour (if yes, why? Seems strange some vars behave  
differently)  
Does anyone have a workaround or solution?

Many thanks in advance if anyone can offer any help.

Cheers  
Neil

Posted at Nginx Forum:

> **[$upstream\_http\_NAME and $sent\_http\_NAME vars not available in certain scopes](https://forum.nginx.org/read.php?2,265734,265734#msg-265734)**
>
> Hi all I am developing a proxy service which uses NGINX to reverse proxy, kind of CDN-like but very specific to our needs. During this. I have hit an issue which I \*think\* is a bug but wanted to ask in case anyone can point to a solution or some...

---

<div class="post-metadata">

**Author:** ![neilstuartcraig](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/9f8e36/32.png) [@neilstuartcraig](https://www.ruby-forum.com/u/neilstuartcraig)\
**Post date:** [March 30, 2016, 5:37pm UTC](https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381/2 "2016-03-30T17:37:12Z")

</div>

Also, for info:

nginx -V  
nginx version: nginx/1.9.13  
built with OpenSSL 1.0.2g 1 Mar 2016  
TLS SNI support enabled  
configure arguments: --prefix=/usr/local/nginx  
–sbin-path=/usr/sbin/nginx  
–conf-path=/etc/nginx/current/nginx.conf --pid-path=/var/run/nginx.pid  
–error-log-path=/var/log/nginx/default-error.log  
–http-log-path=/var/log/nginx/default-access.log  
–lock-path=/var/run/nginx.lock  
–http-client-body-temp-path=/var/cache/nginx/client\_temp  
–http-proxy-temp-path=/var/cache/nginx/proxy\_temp  
–http-fastcgi-temp-path=/var/cache/nginx/fastcgi\_temp  
–http-uwsgi-temp-path=/var/cache/nginx/uwsgi\_temp  
–http-scgi-temp-path=/var/cache/nginx/scgi\_temp --user=gtmdaemon  
–group=gtmdaemon --with-http\_realip\_module --with-http\_v2\_module  
–with-http\_ssl\_module --with-http\_geoip\_module --with-pcre-jit  
–with-ipv6  
–with-file-aio --with-cc-opt=‘-O2 -g -pipe -Wall  
-Wp,-D\_FORTIFY\_SOURCE=2  
-fexceptions -fstack-protector-strong --param=ssp-buffer-size=4  
-grecord-gcc-switches -m64 -mtune=generic’  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/headers-more-nginx-module  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/naxsi/naxsi\_src  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/nginx-module-vts  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/nginx-upstream-dynamic-servers  
–with-openssl=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/openssl-1.0.2g

uname -a  
Linux ip-10-13-149-100.eu-west-1.compute.internal  
3.10.0-327.4.4.el7.x86\_64  
#1 SMP Tue Jan 5 16:07:00 UTC 2016 x86\_64 x86\_64 x86\_64 GNU/Linux

Posted at Nginx Forum:

> **[Re: $upstream\_http\_NAME and $sent\_http\_NAME vars not available in certain scopes](https://forum.nginx.org/read.php?2,265734,265736#msg-265736)**
>
> Hi all I am developing a proxy service which uses NGINX to reverse proxy, kind of CDN-like but very specific to our needs. During this. I have hit an issue which I \*think\* is a bug but wanted to ask in case anyone can point to a solution or some...

---

<div class="post-metadata">

**Author:** ![neilstuartcraig](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/9f8e36/32.png) [@neilstuartcraig](https://www.ruby-forum.com/u/neilstuartcraig)\
**Post date:** [March 30, 2016, 5:37pm UTC](https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381/3 "2016-03-30T17:37:47Z")

</div>

Hello!

On Wed, Mar 30, 2016 at 07:11:45AM -0400, neilstuartcraig wrote:

> a simplified test case I created:  
> […]

> ```
> # This does match - for obvious reasons
> if ($upstream_http_via ~* ".*") {
> 
> # Problem: $upstream_http_via appears not to be populated at this
> 
> ```
> 
> point…  
> set $via\_comp “$upstream\_http\_via 1.y BLAH”;  
> more\_set\_headers “IF\_VIA\_COMP: Value is $via\_comp”;

[…]

> So my questions are:  
> Can anyone see something I have done wrong?  
> Is this expected behaviour (if yes, why? Seems strange some vars behave  
> differently)  
> Does anyone have a workaround or solution?

You are trying to use $upstream\_http\_via in the “if” and “set”  
directives, this is wrong. The $upstream\_http\_via variable is  
only available once a response is returned by an upstream server,  
but the “if” and “set” directives are evaluated before the request  
is sent to the upstream server, see here:

> **[Module ngx\_http\_rewrite\_module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)**

As far as I understand from your config, you want to add something  
to the Via response header. Correct approach would be to only use  
the header after the response is returned, e.g., in the  
“add\_header” directive. Try something like this:

```
map $upstream_http_via $is_via {
    "" "";
    default ", ";
}

server {
    ...

    location / {
        proxy_pass http://upstream;
        proxy_hide_header Via;
        add_header Via "$upstream_http_via$is_via1.1 foo"
    }
}

```

–  
Maxim D.

> **[nginx](http://nginx.org/)**

---

<div class="post-metadata">

**Author:** ![neilstuartcraig](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/9f8e36/32.png) [@neilstuartcraig](https://www.ruby-forum.com/u/neilstuartcraig)\
**Post date:** [March 30, 2016, 5:37pm UTC](https://www.ruby-forum.com/t/upstream-http-name-and-sent-http-name-vars-not-available-in-certain-scopes/244381/4 "2016-03-30T17:37:47Z")

</div>

Also, for info:

nginx -V  
nginx version: nginx/1.9.13  
built with OpenSSL 1.0.2g 1 Mar 2016  
TLS SNI support enabled  
configure arguments: --prefix=/usr/local/nginx  
–sbin-path=/usr/sbin/nginx  
–conf-path=/etc/nginx/current/nginx.conf --pid-path=/var/run/nginx.pid  
–error-log-path=/var/log/nginx/default-error.log  
–http-log-path=/var/log/nginx/default-access.log  
–lock-path=/var/run/nginx.lock  
–http-client-body-temp-path=/var/cache/nginx/client\_temp  
–http-proxy-temp-path=/var/cache/nginx/proxy\_temp  
–http-fastcgi-temp-path=/var/cache/nginx/fastcgi\_temp  
–http-uwsgi-temp-path=/var/cache/nginx/uwsgi\_temp  
–http-scgi-temp-path=/var/cache/nginx/scgi\_temp --user=gtmdaemon  
–group=gtmdaemon --with-http\_realip\_module --with-http\_v2\_module  
–with-http\_ssl\_module --with-http\_geoip\_module --with-pcre-jit  
–with-ipv6  
–with-file-aio --with-cc-opt=‘-O2 -g -pipe -Wall  
-Wp,-D\_FORTIFY\_SOURCE=2  
-fexceptions -fstack-protector-strong --param=ssp-buffer-size=4  
-grecord-gcc-switches -m64 -mtune=generic’  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/headers-more-nginx-module  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/naxsi/naxsi\_src  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/nginx-module-vts  
–add-module=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/nginx-upstream-dynamic-servers  
–with-openssl=/tmp/tmpOzxjVK/BUILD/nginx-1.9.13/openssl-1.0.2g

uname -a  
Linux ip-10-13-149-100.eu-west-1.compute.internal  
3.10.0-327.4.4.el7.x86\_64  
#1 SMP Tue Jan 5 16:07:00 UTC 2016 x86\_64 x86\_64 x86\_64 GNU/Linux

Posted at Nginx Forum:

> **[Re: $upstream\_http\_NAME and $sent\_http\_NAME vars not available in certain scopes](https://forum.nginx.org/read.php?2,265734,265737#msg-265737)**
>
> Hi all I am developing a proxy service which uses NGINX to reverse proxy, kind of CDN-like but very specific to our needs. During this. I have hit an issue which I \*think\* is a bug but wanted to ask in case anyone can point to a solution or some...
