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;
Jan Wrobel
  • 303
  • 1
  • 3
  • 8
  • try `set_if_empty` from https://github.com/openresty/set-misc-nginx-module – SaveTheRbtz Jun 02 '15 at 09: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. – Haravikk Dec 09 '15 at 14:37
  • @Haravikk it looks like that's not the case `nginx: [emerg] "uninitialized_variable_warn" directive is duplicate in` – n1te Oct 26 '18 at 02: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`). – Haravikk Oct 27 '18 at 08:25

5 Answers5

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.

jaseeey
  • 1,462
  • 16
  • 20
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.

timbo
  • 229
  • 2
  • 4
  • 12
0

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

NGT
  • 1
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

ho ilio
  • 1
  • 1
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.

Sam Bull
  • 325
  • 4
  • 12
  • 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). – Sam Bull Mar 08 '23 at 19:14
  • IMHO better than an if statement – Dawesi Aug 28 '23 at 22:24