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://<HOSTNAME>/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 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: https://forum.nginx.org/read.php?2,265734,265734#msg-265734 _______________________________________________ nginx mailing list nginx@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx