Nginx 如果分割目录中存在GZIP缓存文件,则重写,否则发送到PHP;还将bot和未启用GZIP的请求传递给PHP
我正在寻找一种方法,使下面的“重写”/“名称…”仅在重写目标存在(是文件)时发生 我试过使用try_文件,但它抛出了一个404Nginx 如果分割目录中存在GZIP缓存文件,则重写,否则发送到PHP;还将bot和未启用GZIP的请求传递给PHP,nginx,Nginx,我正在寻找一种方法,使下面的“重写”/“名称…”仅在重写目标存在(是文件)时发生 我试过使用try_文件,但它抛出了一个404 location ~* "^/names/(.*?)([^/]{2})([^/]+)" { try_files /cache/html/names/$1$2/$3.html.gz /data/html/names/$1$2/$3.html.gz; if ( $http_accept_encoding ~ "gzip"
location ~* "^/names/(.*?)([^/]{2})([^/]+)" {
try_files /cache/html/names/$1$2/$3.html.gz /data/html/names/$1$2/$3.html.gz;
if ( $http_accept_encoding ~ "gzip" )
{
rewrite "/names/(.*?)([^/]{2})([^/]+)$" /cache/html/names/$1$2/$3.html.gz last;
break;
}
rewrite ^/(.*)$ /index.php?request=$1 last;
break;
}
更新:
这是Apache的代码。注意:它的开头还有一个语言ISO代码,例如/de/。但是英语没有语言代码
RewriteCond %{QUERY_STRING} ^request=([a-z\/]*)names\/(.*?)([^/]{3})([^/]+) [NC]
RewriteRule .* - [E=LANG:%1,E=SN:%2%3/%4]
RewriteCond %{ENV:PATH}/cache/html/%{ENV:LANG}names/%{ENV:SN}.html -f
RewriteRule .* cache/html/%{ENV:LANG}names/%{ENV:SN}.html [L]
完整解决方案:
这是针对我的情况的完整解决方案
我有一些URL,它们有一个可选的语言组件,后跟“name”,后跟一个名称,例如“ivanov”
例如:
/names/ivanov
/de/names/ivanov
这些文件作为以下文件发送到php:
/index.php?request=/de/names/ivanov
PHP将根据某些标准决定是否将名称缓存为.html.gz文件
文件缓存在/cache/html/names/
中
由于存储问题,这些文件被分成由名称的前两个字符组成的目录:
/names/ivanov => /cache/html/names/iv/anov.html.gz
而1-2个字符的名称保存为:
/names/ho => /cache/html/names/ho.html.gz
由于缓存保存为GZIP(以节省约80-90%的磁盘空间),因此需要将任何不接受GZIP的请求推送到PHP而不是缓存
还需要将所有请求从定义的IP列表推送到PHP(而不是GZIP缓存)。这些是用于自动刮片的IP。当检测到它们时,我将它们分配给nginx中的cgi_fastparam。这是在PHP$\u服务器变量中获取的;然后我将随机数据提供给自动刮取机器人。因此,不应允许这些IP查看具有正确变量的GZIP HTML缓存
我使用这种方法,因为流量一度是75%的机器人。通过阻止IP,刮取器能够判断何时没有获得所需的数据。他们可以调整其刮取或增加IP数。但是通过提供随机数据,您完全否定了他们所收集的所有数据的有效性。这导致刮刀的数量减少了100%
代码(感谢下面Ivan的帮助):
在nginx服务器配置之外添加:
map $name $gzfile {
default $name.html.gz;
"~^(.{2})(.+)$" $1/$2.html.gz;
}
geo $scrapers { default 0; 140.227.198.242 1; 127.0.0.1 1; }
映射块根据请求设置值。它删除请求+.html.gz;但如果请求包含三个或更多字符,则将其拆分为iv/anov.html.gz
geo$scrapers块是一个已被识别为自动机器人的IP地址列表。默认情况下,刮刀设置为0;但如果远程主机是已定义的刮板,则会将其分配给1
location ~* "^/([a-z\/]*)names/(.*?)([^/]+)$" {
set $lang $1;
set $page "names";
set $path $2;
set $name $3;
if ($http_accept_encoding !~ gzip) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
if ($scrapers = 1) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
try_files /data/cache/html/$lang$page/$path$gzfile /index.php?request=$lang$page/$path$name;
add_header Content-Encoding gzip;
gzip off;
default_type text/html;
}
位置块拾取匹配的URL:“^/([a-z\/]*)名称/(.*)([^/]+)$
。这是一个可选的(*)语言定义,例如“de”,“ru”
变量由位置正则表达式中的三个(括号)设置
第一个if块检查请求是否不接受GZIP压缩,以及是否将请求重定向到PHP。最后一个标志停止正在处理的块中的进一步代码
第二个块检查访问服务器的IP是否定义为刮板,如果定义为刮板,则将请求推送到PHP,并且不在块中执行进一步的代码
try_files行检查是否存在GZIP HTML缓存并将其加载;否则将请求推送到PHP
最后三行将内容设置为GZIP编码和HTML mime类型。这告诉浏览器压缩内容,响应为HTML。否则浏览器将下载文件或将其显示为GZIP文本
location ~ \.php$
{
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
fastcgi_param SCRAPER $scrapers;
}
上述内容也添加到服务器块中,用于处理PHP。fastcgi_pass和include可能需要与您的系统有所不同
fastcgi_参数行添加了一个变量,可以通过$_服务器['SCRAPER']在PHP中访问该变量。如果在上面列出的nginx geo块中定义了该变量,则该变量将等于“1”;否则等于“0”。如果我正确理解您需要什么,请尝试以下操作:
location ~* "^/names/(.*?)([^/]{2})([^/]+)$" {
set $prefix $1$2;
set $name $3;
if ($http_accept_encoding !~ gzip) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
try_files /cache/html/names/$prefix/$name.html.gz /index.php?request=names/$prefix$name;
}
请注意,try\u files
指令的最后一个参数的含义与所有其他参数不同。作为文档:
如果没有找到任何文件,则会对最后一个参数中指定的uri进行内部重定向
另外,您对last
和break
的使用有点奇怪,在rewrite…last
之后在location
块内使用break
指令没有任何意义$/index.php?request=$1 last;使nginx立即退出当前位置
块,并搜索适合/index.php?request=…
URI的位置
块
更新
根据新OP的要求,更新了解决方案
备选案文1(丑):
变量2(使用map
):
我是否正确理解您的算法?如果((接受gzip编码)和(.html.gz文件存在),则使用.html.gz文件进行响应,否则使用/index.php进行响应?请求=?此外,您是否错过了
^/names/(.*)([^/]{2})([^/]+)结尾的问号
在您的位置中的表达式
定义?谢谢。它工作得近乎完美;而且更加精简。如果这里有一个设施可以给点分数,我会的。您正确理解我需要做什么。就我所知,只有一个问题。对超过2个字符的名称的请求,如/names/shatsky,将是如果存在,则返回到缓存;如果不存在,则返回index.php(生成并缓存页面的位置)。但是,如果名称为1-2个字符(/names/ho),它总是转到index.php。这不是一个大问题,因为只有676个这样的页面。我会看看我是否能做些什么……据我所知,为/names/shatsky
请求生成的页面将是/cache/html/names/sh/atsky.html.gz
。将为/names/sh
或/names/s
生成哪些页面请求?/names/shlocation ~* "^/names/(.*?)([^/]{2})([^/]+)$" {
set $prefix $1$2;
set $name $3;
if ($http_accept_encoding !~ gzip) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
try_files /cache/html/names/$prefix/$name.html.gz /index.php?request=names/$prefix$name;
}
location ~* "^/names/(.*?)([^/]{1,2})([^/]*)$" {
set $path $1;
set $prefix "";
set $name $2.html.gz;
set $suffix $3;
set $full $1$2$3;
if ($suffix) {
set $prefix $2/;
set $name $3.html.gz;
}
if ($http_accept_encoding !~ gzip) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
try_files /cache/html/names/$path$prefix$name /index.php?request=names/$full;
}
map $name $gzfile {
default $name.html.gz;
"~^(.{2})(.+)$" $1/$2.html.gz;
}
server {
...
location ~* "^/names/(.*?)([^/]+)$" {
set $path $1;
set $name $2;
if ($http_accept_encoding !~ gzip) {
rewrite ^/(.*)$ /index.php?request=$1 last;
}
try_files /cache/html/names/$path$gzfile /index.php?request=names/$path$name;
}
...
}