regex - 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; }
}
解决方案
你的解决方案很糟糕,让我告诉你为什么。
现在,与此位置块匹配的每个请求都必须在提供服务之前针对两个 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 的服务器上对其进行了测试,效果很好。
推荐阅读
- ssl - 对 Heroku 上最近部署的一个 js APP 进行 SSL 访问
- powershell - 如何通过单击鼠标来运行提升的脚本?
- android - 带有自定义阵列适配器的微调器
- regex - 正则表达式:匹配除一个特定字符之外的所有内容
- c# - 如何在c#后面的代码中访问数据模板中的网格控件名称
- java - 内部类中的赋值未正确分配
- c# - FtpWebRequest - 身份验证失败,因为远程方已关闭传输流
- error-handling - 为什么 rust 不能使用 "?" 编译 nth() 调用 关键词?
- firebase - dart.global.firebase.storage 为空
- javascript - 如何使用 Lodash.js 删除数组项?