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

时间:2018-08-08 12:48:03

标签: regex nginx nginx-location

我今天已经尝试了很多事情,但我没有赢。我的网站中有一个文件是偶然创建的,带有特殊字符。结果,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以及这个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; } }

3 个答案:

答案 0 :(得分:1)

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

  • 您可以尝试通过以下方式匹配编码URL中的百分比:

    %+

  • 您可以尝试通过以下方式匹配编码URL中的特殊字符:

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

  • 您可以尝试通过以下方式匹配未编码网址中的非ASCII字符:

    [^ \ x00- \ x7F] +

证明:

答案 1 :(得分:1)

临时解决方案

感谢@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; } }

答案 2 :(得分:1)

您的解决方案很糟糕,让我告诉您原因。

现在,与该位置块匹配的每个单个请求都必须在满足条件的情况下针对两个条件进行评估。

任何匹配的请求都将被重定向到正确的网址,该网址也与该位置块匹配,因此现在您的服务器对这些if条件进行了另外两个评估。

只是为了好玩,您还让Nginx根据if条件评估对图像,css和js文件的请求。由于担心pdf,它们都不匹配,但是您仍在请求处理中增加200%的额外开销。

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

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

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的我的一台服务器上对其进行测试,就可以了。