Nginx负向location规则失效求助:非doc/img路径未返回418
Nginx负向Location匹配问题求助
URL示例
1) /store/doc/some_file.doc 2) /store/doc/some_dir/some_file.doc 3) /store/img/some_file.doc 4) /store/img/some_dir/some_file.doc 5) /store/xxx/some_file.doc 6) /store/xxx/some_dir/some_file.doc
当前Nginx配置
location /storage/ { location ^~/storage/[^(doc|img)]/(.*) { return 418; } rewrite ^/storage/(doc|img)/(.*) /storage/_storage.php?type=$1&file=$2 break; }
需求说明
- 所有以
/storage/开头的URL需进行特定处理 - 若URL不匹配
/storage/doc/*或/storage/img/*,返回418状态码("I'm teapot") - 若URL匹配
/storage/doc/*或/storage/img/*,将请求转发至/storage/_storage.php,并携带GET参数:type(取值为doc或img)、file(对应路径后的剩余部分)
当前问题
URL1-4处理正常,但URL5和6未返回418状态码,需要正确的Nginx负向location条件写法。
问题原因
原配置中的[^(doc|img)]是单个字符排除集合,它仅匹配不属于(、d、o、c、|、i、m、g、)的单个字符,而非整个路径段。因此像/storage/xxx/这类路径不会被匹配,自然不会返回418。
解决方案
方案一:利用Location优先级(推荐)
通过先匹配合法路径,剩余请求统一返回418,符合Nginx的匹配逻辑:
location /storage/ { # 优先匹配doc/img路径,转发到处理脚本 location ~ ^/storage/(doc|img)/(.*)$ { rewrite ^/storage/(doc|img)/(.*) /storage/_storage.php?type=$1&file=$2 break; # 若需处理PHP请求,需补充fastcgi_pass等配置,此处保留原逻辑 } # 其他/storage/开头的请求直接返回418 return 418; }
Nginx中正则Location(~)优先级高于前缀Location,因此合法请求会被优先处理,剩下的全部触发418。
方案二:使用if指令配合否定正则
适合简单场景,直接判断请求URI是否不符合合法路径:
location /storage/ { if ($request_uri !~ ^/storage/(doc|img)/) { return 418; } rewrite ^/storage/(doc|img)/(.*) /storage/_storage.php?type=$1&file=$2 break; }
!~表示不匹配后续正则,符合条件的请求直接返回418。
方案三:用负向前瞻修正嵌套Location
如果坚持使用嵌套Location结构,可借助正则负向前瞻断言匹配非doc/img的路径段:
location /storage/ { location ~ ^/storage/(?!doc|img)/ { return 418; } rewrite ^/storage/(doc|img)/(.*) /storage/_storage.php?type=$1&file=$2 break; }
(?!doc|img)是负向前瞻,匹配不是doc或img开头的路径段,从而正确拦截非法请求。
内容的提问来源于stack exchange,提问作者DarkVss
相关产品推荐
相关产品推荐

