Директива карты nginx: почему это разрешено только на уровне http?

В Nginx есть очень полезная директива map.

Но использовать его можно только на уровне http (см. документацию здесь http://nginx.org/en/docs/http/ngx_http_map_module.html#map).

Например, у меня определено server, и я хотел бы использовать некоторые условные перенаправления на этом сервере, используя переменную $url. Было бы очень удобно использовать эту директиву внутри server, но это невозможно. Почему?

Да, я могу сделать это и на уровне http, но могут быть разные server, определенные на уровне http, и я хотел бы сохранить эти условия внутри раздела server, для которого они определены.


person chestozo    schedule 08.12.2014    source источник


Ответы (4)


Довольно старый пост, но я действительно хочу внести немного света в тьму. Сам ответ довольно прост.

DR;TL Переменные в NGINX всегда глобальны и после определения доступны из любой точки конфигурации. Поэтому не имеет смысла определять карту в блоке server или location.

map создает новую переменную, значение которой зависит от значений одной или нескольких исходных переменных, указанных в первом параметре.

пример конфигурации:

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

}

Поскольку переменные в NGINX ВСЕГДА являются глобальными и после определения доступны в любом другом месте конфигурации. Так что нет никакого смысла перемещать карту в локацию или серверный блок. Интересный факт с нашей директивой map заключается в том, когда переменная myvar получит свое значение или когда она будет присвоена?

map присваивает значение переменной после того, как переменная будет использоваться в вашей конфигурации

Это означает, что вы можете определить карту в контексте http, но значение будет присвоено в точке доступа к $myvar в вашей конфигурации nginx.

Вернемся к вашему вопросу: поскольку переменные NGINX всегда являются глобальными, наличие блока map на server имеет смысл, поскольку они в любом случае будут глобальными.

person Timo Stark    schedule 26.02.2021

Я думаю, что на самом деле речь идет о том, каким разработчик создал модуль, и каким он может быть на самом деле.

Я заглянул под капот исходного кода и предложил бы то же самое для большей ясности. Также я использовал следующее руководство, чтобы понять, что означает этот код: https://www.evanmiller.org/nginx-modules-guide.html

Исходный код для ngx_http_map_module находится здесь .

Если я посмотрю на 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 },
  1. Первый параметр просто определяет строку директивы
  2. Второй параметр интересен. Это поле type, которое:

type — это набор флагов, указывающих, где директива допустима и сколько аргументов принимает директива.

Здесь мы видим, что определены поля NGX_HTTP_MAIN_CONF, что делает директиву действительной на уровне http. Но мы не видим соответствующих флагов NGX_HTTP_SRV_CONF - для server или NGX_HTTP_LOC_CONF для location уровней.

Поэтому имеет смысл, что эта конкретная реализация ngx_http_map_module работает только на уровне http.

Теперь, может ли это работать на уровне сервера/локации? Теоретически должно. Но для этого потребуется некоторый вклад в исходный код. Если вы считаете, что это будет полезная функция, пожалуйста, внесите свой вклад :)

person Manish Dash    schedule 08.01.2021

Я думаю, что если вы используете карту для редиректов - это не очень хорошо в конфигах nginx. Может быть, переписывание решит вашу проблему? Смт. как https://www.nginx.com/blog/creating-nginx-rewrite-rules/

person Talkerbox    schedule 03.05.2019

Область, в которой можно использовать map, зафиксирована в исходном коде nginx. Ниже приведена часть кода из ngx_http_map_module.c. Вы можете видеть, что map можно использовать только на NGX_HTTP_MAIN_CONF, что означает только http уровень.

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 },
person D3Hunter    schedule 08.12.2014
comment
Спасибо ) Знаешь почему сейчас так? - person chestozo; 08.12.2014
comment
Сказать, что программное обеспечение не позволяет это, констатировать очевидное. Спрашивать, почему, значит спрашивать, какова была причина такого выбора. - person HostedMetrics.com; 15.01.2018