Nginx 位置匹配特殊字符和编码 url 个字符的正则表达式

Nginx location match regex for special characters and encoded url characters

今天我尝试了很多东西,但就是没有成功。我的站点中有一个文件是偶然创建的,其中包含一个特殊字符。因此,Googlebot 已经停止抓取 3 周了,网站管理员工具/搜索控制台不断通知我并希望重新测试 url。

我想要实现的是配置 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 还有这个 How do I redirect all requests that contains a certain string to 404 in nginx?

现在可以 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; } }

我不了解 Nginx 及其处理正则表达式的方式,但是 :

  • 您可以尝试将编码的 URL 中的百分比与:

    进行匹配

    %+

  • 您可以尝试匹配编码 URL 中的特殊字符:

    (%([A-Z][0-9]|[0-9][A-Z]|[0-9]+|[A-Z]+))+

  • 您可以尝试在未编码的 URL 中匹配非 ASCII 字符:

    [^\x00-\x7F]+

证明:

临时解决方案

感谢@funilrys 还有这个How do I redirect all requests that contains a certain string to 404 in nginx?

现在可以 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; } }

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

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

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

为了好玩,您还让 Nginx 根据您的 if 条件评估对图像、css 和 js 文件的请求。 None 它们会匹配,因为您担心 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,很有魅力。