首页 > 解决方案 > Nginx 位置匹配正则表达式的特殊字符和编码的 url 字符

问题描述

我今天尝试了很多事情,但我没有赢。我的站点中有一个文件是偶然创建的,其中包含一个特殊字符。结果,Googlebot 现在已经停止抓取 3 周,并且网站管理员工具/搜索控制台不断通知我并希望重新测试该网址。

我想要实现的只是配置 Nginx 以匹配以下请求并将它们重定向到正确的位置,但正则表达式让我很难过。

未编码的 URL 字符串是:

/historical-rainfall-trends-south-africa-1921–2015.pdf

编码后的 URL 字符串为:

/historical-rainfall-trends-south-africa-1921%C3%A2%E2%82%AC%E2%80%9C2015.pdf

我怎样才能获得这些的位置匹配?

更新:

仍然失去理智,我没有尝试过任何工作。我在这里得到了这个正则表达式的匹配 - https://regex101.com/r/3Lk2zr/3

但是然后使用这个

location ~ /.*[^\x00-\x7F]+.* { return 444; }

仍然给我一个 404 而不是 444

同样,我得到了一个匹配 - https://regex101.com/r/80KWJ8/1 但是然后

location ~ /.*([^?]*)\%(.*)$ { return 444; }

给出 404 而不是 444

也试过这个,但仍然没有工作。来源:https ://serverfault.com/questions/656096/rewriting-ascii-percent-encoded-locations-to-their-utf-8-encoded-equivalent

location ~* (*UTF8).*([^?]*)\%(.*)$ { return 444; }

location ~* (*UTF8).*[^\x00-\x7F]+.* { return 444; }

临时解决方案

感谢@funilrys 以及如何将包含某个字符串的所有请求重定向到 nginx 中的 404?

现在可以 100% 使用

location /resources { expires 3h; add_header Cache-Control 'must-revalidate, proxy-revalidate, max-age=10800'; location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 3h; add_header Cache-Control 'must-revalidate, proxy-revalidate, max-age=10800'; } location ~* \.(pdf)$ { expires 30d; add_header Cache-Control 'must-revalidate, proxy-revalidate, max-age=2592000'; if ($request_uri ~ .*%.*) { return 301 https://example.com/resources/weather-documents/historical-rainfall-trends-south-africa_1921_2015.pdf; } if ($request_uri ~ .*[^\x00-\x7F]+.*) { return 301 https://example.com/resources/weather-documents/historical-rainfall-trends-south-africa_1921_2015.pdf; } }

标签: regexnginxnginx-location

解决方案


你的解决方案很糟糕,让我告诉你为什么。

现在,与此位置块匹配的每个请求都必须在提供服务之前针对两个 if 条件进行评估。

任何匹配的请求都会被重定向到正确的 url,它也匹配这个位置块,所以现在你的服务器正在对这些 if 条件进行另外两次评估。

只是为了好玩,你也让 Nginx 评估你的 if 条件对图像、css 和 js 文件的请求。它们都不匹配,因为您担心 pdf,但您仍然为请求处理增加了 200% 的额外开销。

一个对 Nginx 更友好的解决方案实际上非常简单。

Nginx 按照位置指令在您的配置中列出的顺序进行正则表达式匹配,并选择第一个匹配块,因此如果此文件 url 将匹配您的任何其他正则表达式指令,那么您需要将此块放在这些位置之上:

location ~* /historical-rainfall-trends-south-africa-1921([^_])*?2015\.pdf$ {
    return 301 https://example.com/resources/weather-documents/historical-rainfall-trends-south-africa_1921_2015.pdf;
}

刚刚在我的一台运行 Nginx 1.15.1 的服务器上对其进行了测试,效果很好。


推荐阅读