19

I need to set a variable to a default value if it is not already set. Following config does the job:

if ($foo ~ "^$") { set $foo default-value; } 

But it generates runtime warnings:

using uninitialized "foo" variable

Is there a way to test if a variable is set without generating the warning and without turning off the warning globally with:

uninitialized_variable_warn off; 
4
  • try set_if_empty from github.com/openresty/set-misc-nginx-module Commented Jun 2, 2015 at 9:26
  • 2
    Just found this while looking for something similar, but it seems like uninitialized_variable_warn doesn't need to be set globally, you can just set it where you need to use potentially uninitialised variables. I'm using this for passing SSL details to PHP, which will be empty if the page is accessed without SSL. Commented Dec 9, 2015 at 14:37
  • @Haravikk it looks like that's not the case nginx: [emerg] "uninitialized_variable_warn" directive is duplicate in Commented Oct 26, 2018 at 2:20
  • Do you still have it set somewhere else? I'm using uninitialized_variable_warn as part of a php.conf that's imported only by locations that support PHP, so I'm definitely using it only in those scopes, while leaving the warning everywhere else. I don't have uninitialized_variable_warn set at any other scope though (letting it default to true). Commented Oct 27, 2018 at 8:25

5 Answers 5

13

I'm using the following to check if a variable exists:

if ($dir = false) { set $dir ""; } 

If it's not set before it reaches this location block, then it will set it to a blank string. You can just as easily add a string between the quotes. I do not get any errors when doing a configuration test using this.

Please let me know if you're seeing otherwise.

2
  • I am seeing nginx: [emerg] unknown "dir" variable Commented Aug 11, 2017 at 6:47
  • 3
    This false check does not work anymore, please use $foo ~ "^$" Commented May 2, 2019 at 14:18
2

The behaviour seems to have changed or at least be different for query parameter values using $arg_<name>. On nginx 1.13.6, using the following to check if a query value in the ngx variable exists:

if ($arg_test = false) { default_type 'text/plain'; return 404; } 

does not pass to the 404. Using:

if ($arg_test = '') { default_type 'text/plain'; return 404; } 

returns a 404, if the query parameter does not exist. Useful for not hitting upstream if a required query parameter does not exist.

1

I think the simple answer is that you ought to use a map, but none of the answers here or in similar questions were an approach that worked for my usage in the latest Nginx versions, so for those situations the below seems to work.

In my case I needed to overwrite the Host header, conditionally, in an included general configuration file shared by many sites, whilst only setting that for the sites that needed it.

In this case, in your http block (e.g. nginx.conf):

map '' $proxied_host { default ''; } map "$proxied_host" $resolved_host { default $host; ~. $proxied_host; } 

and in the included configuration file in every location:

proxy_set_header Host $resolved_host:$server_port; 

then in the sites that need to overwrite it, in the location block:

set $proxied_host your.example.com; 

This is the only way I found to avoid:

  1. Floods of warnings in error.log saying using uninitialized "proxied_host" variable
  2. Errors related to using uninitialized variables in the map like nginx: [emerg] unknown "proxied_host" variable
  3. Errors relating to cycles in variables cycle while evaluating variable "proxied_host"

These last two errors appeared when following the answers in this question

0

If GET QUERY parameter detection

e.g: foo.com?proxy proxy variable exists Do not use $arg_proxy

if ($args ~ '(&|^)proxy([&=]|$)' ) { #exists set $port '8080'; } https://forum.nginx.org/read.php?2,224860,224860

0

An easy option, if you're optionally setting the variable in an included file, is simply to set the default value first.

set $value 'default'; include maybe-set-value.conf; 

The second set statement in the conf file will replace the default value.

2
  • Not sure why someone downvoted this without providing any rationale. The question relates to setting a default value, which this answer achieves while avoiding the difficulties of using if (which if reading the nginx documentation, comes with lots of warnings and is often easier to avoid if another solution is possible). Commented Mar 8, 2023 at 19:14
  • IMHO better than an if statement Commented Aug 28, 2023 at 22:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.