43

There is a very useful directive in Nginx map.

But it is possible to use it only on the http level (see docs here http://nginx.org/en/docs/http/ngx_http_map_module.html#map).

For example, I have a server defined and I would like to use some conditional redirects in this server using $url variable. It would be very handy to use this directive inside server but it is not possible. Why?

Yes, I can do it also on the http level but there may be different servers defined on the http level and I would like to keep these conditions inside server section they are defined for.

3 Answers 3

27

Pretty old post but I really 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 configuration. Therefore 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 not make sense as they would be global anyway.

2
  • 1
    As NGINX variables are always global having a map per server block would make sense as they would be global anyway. Would or would not?
    – izogfif
    Jun 15, 2022 at 0:51
  • Would NOT. Thanks for pointing me to that one. Updated.
    – Timo Stark
    Jun 28, 2022 at 10:31
3

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 :)

0
-3

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 },
2
  • 1
    Thank you ) Do you know why it is like it is now?
    – chestozo
    Dec 8, 2014 at 15:48
  • 12
    Saying the software doesn't allow it is stating the obvious. Asking "why" is asking what the reasoning for that choice was. Jan 15, 2018 at 0:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.