nginx map directive: why is it allowed only on http level? nginx map directive: why is it allowed only on http level? nginx nginx

nginx map directive: why is it allowed only on http level?


Pretty old post but I realy want to bring some light into the darkness. The answer itself is quite simple.

DR;TL Variables in NGINX are always global and once defined accessable from anywhere in the configration. Therfore it would not make any sense to define a map in a server or location block.

map creates a new variable whose value depends on values of one or more of the source variables specified in the first parameter.

example configuration:

map $host $myvar {example.com "test";foo.com     "for";}

As variables in NGINX are ALWAYS global and once defined available anywhere else in the configuration. So it wouldn't make any sense to move the map into a location or server block. The interesting fact with our map directive is when the variable myvar will receive its value or when it will be assigned?

map assigns the value to the variable once the variable will be used in your configuration

That means you can define the map in the http context but the value will be assigned at the point you are accessing $myvar in your nginx configuration.

Back to your question:As NGINX variables are always global having a map per server block would make sense as they would be global anyway.


I think its really about what the developer has built the module to be vs how it can actually be.

I took at look under the hood at the source code and I would suggest the same for more clarity. Also I used the following guide to understand what that code means : https://www.evanmiller.org/nginx-modules-guide.html

The source code for the ngx_http_map_module is here.

If I look at the static ngx_command_t ngx_http_map_commands[] = {...} which defines the directives of the module and specifically at the following snippet:

 { ngx_string("map"),  NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,  ngx_http_map_block,  NGX_HTTP_MAIN_CONF_OFFSET,  0,  NULL },
  1. The first parameter just defines the directive string
  2. The second parameter is interesting. Its the type field which is:

type is a set of flags that indicate where the directive is legal and how many arguments the directive takes.

We see here that the fields defined are NGX_HTTP_MAIN_CONF which makes the directive valid at the http level. But we do not see the corresponding flags NGX_HTTP_SRV_CONF - for server or NGX_HTTP_LOC_CONF for location levels.

So it makes sense that this particular implementation of the ngx_http_map_module only works at the http level.

Now, can it work on the server/location level? Theoretically, it should. But it would need some contribution in the source code. If you think it would make for a useful feature, please do contribute :)


The scope where map can be used is fixed in nginx source code. Below is part of code from ngx_http_map_module.c. You can see map can only be used in NGX_HTTP_MAIN_CONF which means http level only.

static ngx_command_t  ngx_http_map_commands[] = {                                                                                                          { ngx_string("map"),                                                                                                                                     NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,                                                                                                      ngx_http_map_block,                                                                                                                                    NGX_HTTP_MAIN_CONF_OFFSET,                                                                                                                             0,                                                                                                                                                     NULL },