使用Nginx map模块实现精确字面匹配优先于正则匹配
Nginx精确匹配重定向优先于正则的解决办法
问题根源
- 一开始用
location块时,正则location的优先级本来就比精确location高,导致精确映射被正则规则覆盖。 - 换成
map后完全不生效,大概率是你把map写进server块里了——map是Nginx全局http级的指令,不能嵌套在server块内;另外也可能是blogs.map的格式不符合要求。
正确配置步骤
1. 把map移到http上下文
map必须定义在http块(所有server块的外层)中,否则Nginx无法识别这个映射规则,自然不会生效。
2. 修正完整配置
保持精确匹配列表(从blogs.map导入)在正则规则前面,因为map是按从上到下的顺序匹配的,先匹配到精确条目就会停止后续匹配,正好实现精确优先的需求。
完整配置示例:
http { # 这里保留你的其他全局配置,比如include mime.types;等 map_hash_bucket_size 256; map $request_uri $new_uri { # 先加载精确匹配列表,优先级最高 include /etc/nginx/redirect/blogs.map; # 正则规则,仅当没有匹配到精确条目时生效 ~^/[0-9]{4}/[0-9]{2}/[0-9]{2}/(.*)$ /blog/$1; } server { listen 8080; listen [::]:8080; server_name _; absolute_redirect off; root /usr/share/nginx/html; index index.html index.htm; error_page 404 /404.html; charset utf-8; if ($new_uri) { return 301 $new_uri; } location / { try_files $uri $uri/ /index.html; } } }
3. 检查blogs.map的格式
文件内的每一条精确映射必须符合精确URI 目标URI;的格式,示例:
/2002/03/12/slug-of-blog /something-else; /old-about /about; /legacy-contact /contact-us;
- 每条结尾必须加分号
- 精确URI要和请求路径完全一致(包括开头的斜杠);如果不需要匹配URL中的查询参数,建议把
map里的$request_uri换成$uri($uri仅包含路径部分,不会受查询参数影响)。
4. 验证配置并重启Nginx
先检查配置是否有语法错误:
nginx -t
如果没有报错,重启Nginx使配置生效:
systemctl restart nginx
原理说明
Nginx的map指令会按配置顺序匹配:先遍历所有精确条目,匹配成功后直接返回结果,不会再执行后续的正则规则,完美实现精确匹配优先的需求。同时,把map放在http上下文,才能让server块中的$new_uri变量正确获取映射值。
内容的提问来源于stack exchange,提问作者Luke Vincent
相关产品推荐
相关产品推荐

