nginx map 指令:为啥只允许在 http 级别?
Posted
技术标签:
【中文标题】nginx map 指令:为啥只允许在 http 级别?【英文标题】:nginx map directive: why is it allowed only on http level?nginx map 指令:为什么只允许在 http 级别? 【发布时间】:2015-02-06 03:45:08 【问题描述】:nginx 中有一个非常有用的指令map
。
但只能在http
级别使用它(请参阅此处的文档http://nginx.org/en/docs/http/ngx_http_map_module.html#map)。
例如,我定义了一个server
,我想使用$url
变量在此服务器中使用一些条件重定向。在server
中使用这个指令会非常方便,但这是不可能的。 为什么?
是的,我也可以在 http
级别上执行此操作,但在 http
级别上定义的 server
s 可能不同,我想将这些条件保留在为它们定义的 server
部分中。
【问题讨论】:
【参考方案1】:相当老的帖子,但我真的想给黑暗带来一些光明。答案本身很简单。
DR;TL NGINX 中的变量总是全局的,一旦定义就可以从配置中的任何地方访问。因此,在 server
或 location
块中定义地图没有任何意义。
map
创建一个新变量,其值取决于第一个参数中指定的一个或多个源变量的值。
示例配置:
map $host $myvar
example.com "test";
foo.com "for";
因为 NGINX 中的变量始终是全局的,并且一旦定义就可以在配置中的其他任何地方使用。因此,将地图移动到位置或服务器块没有任何意义。 map
指令的一个有趣事实是变量 myvar
何时会收到其值或何时分配?
一旦变量将在您的配置中使用,map 就会将该值分配给该变量
这意味着您可以在 http 上下文中定义映射,但该值将在您访问 nginx 配置中的$myvar
时分配。
回到你的问题:
由于 NGINX 变量总是全局的,每个 server
块有一个 map
是有意义的,因为它们无论如何都是全局的。
【讨论】:
【参考方案2】:我认为这真的是关于开发人员构建模块是什么与它实际上可以是什么。
我查看了源代码的底层内容,为了更清晰,我建议您这样做。我还使用以下指南来了解该代码的含义:https://www.evanmiller.org/nginx-modules-guide.html
ngx_http_map_module
的源代码是here。
如果我查看定义模块的指令的static ngx_command_t ngx_http_map_commands[] = ...
,特别是以下sn-p:
ngx_string("map"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
ngx_http_map_block,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
NULL ,
-
第一个参数只是定义了指令字符串
第二个参数很有趣。它的
type
字段是:
type 是一组标志,指示指令在哪里是合法的以及指令需要多少个参数。
我们在这里看到定义的字段是NGX_HTTP_MAIN_CONF
,这使得指令在http 级别有效。但是我们没有看到相应的标志NGX_HTTP_SRV_CONF
- 用于server
或NGX_HTTP_LOC_CONF
用于location
级别。
因此,ngx_http_map_module
的这种特定实现仅在 http 级别有效。
现在,它可以在服务器/位置级别上运行吗?从理论上讲,它应该。但它需要在源代码中做出一些贡献。如果您认为它会成为一个有用的功能,请做出贡献:)
【讨论】:
【参考方案3】: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 ,
【讨论】:
谢谢)你知道为什么会变成现在这样吗? 说软件不允许它是显而易见的。问“为什么”就是问那个选择的理由是什么。以上是关于nginx map 指令:为啥只允许在 http 级别?的主要内容,如果未能解决你的问题,请参考以下文章