先看 Nginx Tutorial #1 Basic Concepts(链接,存档)讲得清晰明了。
不在任何 context 下的 directive 被称为 global configuration directive。这些 directive 也可以通过 nginx 命令行来配置。
如何判断一个请求被哪个 server 及 location 处理?官方文档 有描述具体的逻辑。Digital Ocean 也有一篇非常详细的 讲解文章。这是 nginx 中比较复杂的一环。
location 匹配
location context 一般的样式是:
location <optional_modifier> <location_match> {
# ...
}
比如:
location ~ \.(jpe?g|png|gif|ico)$ {
# ...
}
modifier 是针对 location 而言的(不对其他 directive 通用),有 4 种,官方文档 有描述,Digital Ocean 的 文档 也有非常好的描述。总结如下:
不指定 | 普通字符串,前缀匹配 |
= | 普通字符串,精确匹配,优先级最高 |
~ | 正则表达式,区分大小写匹配 |
~* | 正则表达式,不区分大小写匹配 |
^~ | 普通字符串,前缀匹配;一旦匹配成功,不再走正则表达式匹配 |
location 匹配逻辑如下:
- 如果有普通字符串精确匹配(
=
),使用这个 location - 找到最长的普通字符串前缀匹配,记录下来
- 如果这个最长匹配是
^~
,使用这个 location;否则依次执行正则匹配,使用第一个匹配成功的 location - 找不到任何匹配的 location 时,返回 404
正则表达式
nginx 使用了 PCRE 库来处理 regexp。配置中对 regexp 的使用不够有一致性,比如:
# location 使用了一个单独的 modifier 来表示是否为一个 regexp:
location ~* \.(gif|jpg|jpeg)$ {
# ...
}
# server_name 及 map 则使用了 ~ 或者 ~* 来表示一个 regexp:
server {
listen 80;
server_name ~^(?<user>.+)\.example\.net$;
...
}
map $uri $isphp {
~\.php$ 1;
default 0;
}
这点是反直觉的。nginx 的正则能力并不是通用的(universal),而是跟具体的 directive 是否支持、如何支持有关。