更新脚本
我已经彻底修改了这个脚本,现在我更加意识到这是一个数组,我们在这里所做的每个重定向只是添加到它。我也学到了很多关于函数的知识,现在它非常便携,同时还能做更多的事情。
这是完整的新脚本。和之前比起来简直是一头野兽,但是之前实在是太乱了。
function redirects($config) { // Create a redirects(); function with the inputted array set as $config
// Config Variables
$req = $config['param']; // Assign $req to the $config param value
$dir = $config['dir']; // Assign $dir to the $config dir value
$domain = $config['domain']; // Assign $domain to the $config domain value
$_404 = $config['404']; // Assign $_404 to this $config 404 value
$_referer = $config['referer']; // Assign $referer_ to the referer value
$referer = 'referer='.$_referer; // Assign $referer to the full referer param
if (isset($_GET[$_referer])) {
if ($_GET[$_referer] == $_referer) { // If this script's referer exists,
echo "Do not loop back to the script!"; // Throw a warning
exit(); // & exit
} // Otherwise continue
}
if (isset($_GET[$req]) && !empty($_GET[$req])) { // If a req parameter exists & isn't empty, continue
$req = $_GET[$req]; // Assign $req to $_GET[$req]
// Create the arrays
$redirects = $wildcards = $halfwilds = array(); // Create the arrays needed, so if there's not at least one redirect done, which would be what creates the array otherwise, there won't be a 500 error due to it.
// Redirect includes
foreach (glob($dir) as $filename) { // Search for all redirect php files at $dir location
include $filename; // Include those files
}
// Leading & Trailing Slashes
$req = '/'.trim($req, '/').'/'; // Add a leading & trailing slash to $req param if non existent
function redir_editkeys($array) { // Create an editkeys(); function and pass the specified array as $array
$keys = array_keys($array); // Extract the keys of the array as values of $keys array
foreach ($keys as &$value) {
$value = '/'.trim($value, '/').'/'; // Add a leading & trailing slash to $keys values if non existent
}
return array_combine($keys, $array); // Replace the original array's keys with the modified keys & return
}
// Referer
function referer($redir, $referer, $domain) { // Create a referer(); function and pass to it $redir, $referer, & $domain.
if (strpos($redir, $domain) !==false) { // Using $domain, check $redir for a match.
$redir = $redir.'?'.$referer; // If there's a match, add the referer param
} return $redir; // Return the edited $redir, or if no match, return without editing
}
// Redirects
$redirects = redir_editkeys($redirects); // Edit $redirects keys using editkeys();
if (isset($redirects[$req])) { // Check that $redirects[$req] exists
$redir = $redirects[$req]; // Assign $redir to $redirects[$req];
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
// Wildcards
$wildcards = redir_editkeys($wildcards); // Edit $wildcards keys using editkeys();
foreach ($wildcards as $key => $value) { // Assign variables to $wildcards keys & values
if (strpos($req, $key) !== false) { // Using $key, check $req for a match
$wild = substr($req, strlen($key)); // Extract everything after the match as $wild
$req = substr($req, 0, strlen($key)); // Extract the matching part at the beginning as $req
if (isset($wildcards[$req])) { // Check that $wildcards[$req] exists
$redir = $wildcards[$req]; // Assign $redir to $wildcards[$req]
$redir = $redir.$wild; // Attach $wild onto $redir
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
}
}
// Half Wilds
$halfwilds = redir_editkeys($halfwilds); // Edit $halfwilds keys using editkeys();
foreach ($halfwilds as $key => $value) { // Assign variables to $halfwilds keys & values
if (strpos($req, $key) !== false) { // Using $key, check $req for a match
$req = substr($req, 0, strlen($key)); // Extract the matching part at the beginning as $req
if (isset($halfcards[$req])) { // Check that $halfwilds[$req] exists
$redir = $halfwilds[$req]; // Assign $redir to $halfwilds[$req]
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
}
}
// 404
$req = "req=".trim($req,'/')."&"; // Attach the param name to the $req value for the 404 redirect if it's not empty and remove the slashes.
}
else { $req = ''; } // If no req param, or if empty, unset $req
header("Location: ".$domain.$_404."?".$req.$referer); // If there's no match, redirect to this location.
}
我们通过以下方式调用此脚本:
redirects(
array( // Config
'param' => 'req', // Param name || Set the name of the url param. Here it is "req".
'dir' => 'redirects/*/*.php', // Redirect file(s) location || Set the location to look for the file(s) you store your redirects. Here I have my files in sub folders of a rediects folder. Do not put a leading slash infront, use "../" etc as it must be relative, not absolute..
'domain' => 'http://domain.tld', // Your domain || Set your website's domain name here. This'll be used to check whether redirects go to it and if the referer is needed.
'404' => '/', // 404 location || Set the location 404s will go to. Hereit is just my homepage, so I've put "/".
'referer' => 'redirector' // Referer param || Set the value of the referer param that will be used in redirects to the same site so we can stop 404s resulting in a loop.
)
);
要做简单的重定向,我们可以这样做:
$redirects['request1'] = "$domain/dest1";
$redirects['request2'] = "$domain/dest2";
要做通配符,我们可以这样做:(确保在末尾添加斜杠,除非它是目标,例如查询字符串)
$wildcards['request3'] = "$domain/dest3/";
$wildcards['request4'] = "$domain/dest4/";
而且我还添加了半个通配符,所以如果你想将request5/anypath 发送给$domain/dest5,而不是dest5/anypath,我们可以这样做:
$halfwilds['request5'] = "$domain/dest5";
$halfwilds['request6'] = "$domain/dest6";
让我们把它分成块,看看每个部分在做什么:
- 配置:
首先,我们以$config 数组作为参数启动redirects(); 函数。然后我们为每个设置分配变量。
function redirects($config) { // Create a redirects(); function with the inputted array set as $config
// Config Variables
$req = $config['param']; // Assign $req to the $config param value
$dir = $config['dir']; // Assign $dir to the $config dir value
$domain = $config['domain']; // Assign $domain to the $config domain value
$_404 = $config['404']; // Assign $_404 to this $config 404 value
$_referer = $config['referer']; // Assign $referer_ to the referer value
$referer = 'referer='.$_referer; // Assign $referer to the full referer param
我们有两个用于引用的变量,一个用于引用值,第二个作为完整的参数连接起来用于重定向。
- 推荐人检查
我首先检查了请求中是否存在此脚本的引用参数,只需简单地说"Do not loop back to the script!",然后是exit(); 脚本。
if (isset($_GET[$_referer])) {
if ($_GET[$_referer] == $_referer) { // If this script's referer exists,
echo "Do not loop back to the script!"; // Throw a warning
exit(); // & exit
} // Otherwise continue
}
- 数组和包含
接下来,如果请求中的referer参数不匹配,当req参数存在且不为空时,我们打开一个if for,创建空数组,然后包含我们在配置中声明的位置'正在放置我们的重定向。
if (isset($_GET[$req]) && !empty($_GET[$req])) { // If a req parameter exists & isn't empty, continue
$req = $_GET[$req]; // Assign $req to $_GET[$req]
// Create the arrays
$redirects = $wildcards = $halfwilds = array(); // Create the arrays needed, so if there's not at least one redirect done, which would be what creates the array otherwise, there won't be a 500 error due to it.
// Redirect includes
foreach (glob($dir) as $filename) { // Search for all redirect php files at $dir location
include $filename; // Include those files
}
根据我对 php 工作方式的理解,这实际上有一个好处,将包含放在 if 中,如果不满足条件,当请求没有 req 参数时,包含不会'甚至没有得到处理。
- 前导和尾随斜杠
按照之前脚本的情况,我们必须确保在重定向键的末尾添加斜杠,并在参数末尾使用斜杠向脚本发送请求。让我们通过使用 trim(); 来消除这样做的需要'狗/'。
// Leading & Trailing Slashes
$req = '/'.trim($req, '/').'/'; // Add a leading & trailing slash to $req param if non existent
function redir_editkeys($array) { // Create an editkeys(); function and pass the specified array as $array
$keys = array_keys($array); // Extract the keys of the array as values of $keys array
foreach ($keys as &$value) {
$value = '/'.trim($value, '/').'/'; // Add a leading & trailing slash to $keys values if non existent
}
return array_combine($keys, $array); // Replace the original array's keys with the modified keys & return
}
在这里,我们创建了一个名为 editkeys(); 的函数,它创建一个新数组,其中包含您传递给它的任何数组的键,执行一个 foreach 来修改这些键,然后将它们放回原始数组中,替换原来的键。
- 目标域检查是否需要引用参数
如果我们将目标的 404 请求发送到脚本,我们希望停止重定向循环以重定向到以 404 结尾的目标。我们可以只添加referer 参数,但这可能会根据该目的地的网站配置对查询字符串的处理而冒出错误的风险。所以让我们做一个函数来检查传递的目的地是否到达$domain,如果为真则添加引用者并将其返回。
// Referer
function referer($redir, $referer, $domain) { // Create a referer(); function and pass to it $redir, $referer, & $domain.
if (strpos($redir, $domain) !==false) { // Using $domain, check $redir for a match.
$redir = $redir.'?'.$referer; // If there's a match, add the referer param
} return $redir; // Return the edited $redir, or if no match, return without editing
}
- 重定向
接下来我们有将重定向放在一起的部分。首先,我们有简单的重定向。首先,我们通过editkeys();函数运行$redirects数组,然后它检查匹配的键是否在数组中,在目标上运行上面的referer();函数,然后重定向到它。
// Redirects
$redirects = redir_editkeys($redirects); // Edit $redirects keys using editkeys();
if (isset($redirects[$req])) { // Check that $redirects[$req] exists
$redir = $redirects[$req]; // Assign $redir to $redirects[$req];
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
其次是通配符。我们通过editkeys();函数运行$wildcards数组,在数组上运行foreach();来寻找匹配的key,得到匹配后的所有东西为$wild,只得到匹配为$req,检查$req 值作为键存在于数组中,获取该键的目的地,附加 $wild,然后运行检查是否需要引用者,重定向和 bam。
// Wildcards
$wildcards = redir_editkeys($wildcards); // Edit $wildcards keys using editkeys();
foreach ($wildcards as $key => $value) { // Assign variables to $wildcards keys & values
if (strpos($req, $key) !== false) { // Using $key, check $req for a match
$wild = substr($req, strlen($key)); // Extract everything after the match as $wild
$req = substr($req, 0, strlen($key)); // Extract the matching part at the beginning as $req
if (isset($wildcards[$req])) { // Check that $wildcards[$req] exists
$redir = $wildcards[$req]; // Assign $redir to $wildcards[$req]
$redir = $redir.$wild; // Attach $wild onto $redir
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
}
}
然后我们有一半通配符,它们或多或少是相同的。我自己并没有任何真正的理由,但肯定有原因,例如您已经摆脱了整个投资组合画廊并希望向该画廊发送请求以及对图像的子请求等回到投资组合,这将完成工作。所以它是脚本的一部分。
// Half Wilds
$halfwilds = redir_editkeys($halfwilds); // Edit $halfwilds keys using editkeys();
foreach ($halfwilds as $key => $value) { // Assign variables to $halfwilds keys & values
if (strpos($req, $key) !== false) { // Using $key, check $req for a match
$req = substr($req, 0, strlen($key)); // Extract the matching part at the beginning as $req
if (isset($halfcards[$req])) { // Check that $halfwilds[$req] exists
$redir = $halfwilds[$req]; // Assign $redir to $halfwilds[$req]
$redir = referer($redir, $referer, $domain); // If it does, run referer();
header("Location: $redir"); // & Redirect
exit();
}
}
}
我确实想尝试做一个函数来保存这个大量重复的代码,但是foreach(); 的代码实在是太尴尬了。
- 404
然后我们有 404 重定向,它将任何与请求不匹配的请求作为 req 参数发送回脚本,或者如果没有 req 参数或如果它为空,则仅与引用参数匹配。
// 404
$req = "req=".trim($req,'/')."&"; // Attach the param name to the $req value for the 404 redirect if it's not empty and remove the slashes.
}
else { $req = ''; } // If no req param, or if empty, unset $req
header("Location: ".$domain.$_404."?".$req.$referer); // If there's no match, redirect to this location.
}
这就是脚本。
现在,向脚本发送无效请求。
Apache / Litespeed / Openlitespeed (htaccess)
在您的 htaccess 底部,添加以下内容:
############# Rewrite dead requests to redirector with uri as query
RewriteCond %{QUERY_STRING} !referer=redirector [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /redirect.php?req=$1 [R=301,L]
#############
Nginx
在服务器的 (vhost) conf 中添加这个:
############# Send dead requests to redirector with uri as query
error_page 404 = @redirects;
location @redirects {
if ($query_string !~ referer=redirector {
rewrite ^/(.*)(.php?) /redirect.php?req=$1 redirect;
}
}
#############
我现在正在使用 Nginx,因为出现了一个 Nginx 根本没有的奇怪问题,因此不再使用 OpenLitespeed。所以弄清楚 Nginx conf 的做事方式很有趣。我注意到的一件事是,通过将扩展请求重写为无扩展,发送到其他地方的请求会在最后添加 .php。因此,我必须在此处的重写中排除扩展名。同样在error_page 404 的位置执行这些通配符重定向,比尝试在if 中设置以忽略现有文件/文件夹要容易得多。
删除目标请求的引用参数。
在尝试对 nginx 执行与 htaccess 相同的操作时,删除引用参数,我尝试这样做很有趣,但我意识到无论如何这都是一个有缺陷的解决方案,因为它删除了整个查询.
使用 PHP 来代替,这个函数就是为了实现这一点,删除一个参数:
function strip_param($url,$param) {
if (isset($_GET[$param])) { // Check that param exists
$base_url = strtok($url,'?'); // Get the base url
$parsed_url = parse_url($url); // Parse it
$query = $parsed_url['query']; // Get the query string
parse_str($query,$params); // Convert parameters into array
unset($params[$param]); // Delete the one you want
$new_query = http_build_query($params); // Rebuild query string
$new_url = $base_url.'?'.$new_query; // Rebuild the url
$url = rtrim($new_url,'?'); // If now no query, remove ending ?
return header("Location: $url"); // Redirect
}
}
// How to use
//
// Place the above function anywhere you include above content of where you need it, such as a functions file.
// The below, put this somewhere at the top before content.
// Strip params from requests
strip_param($webpage_URI,'referer'); // The $webpage_URI value is: "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
这个功能我们可以give props to this person for。
这就是导致我开始克隆它的评论方式的原因。这是一种整洁、易读的做事方式。尽管我之前的剧本很短,但它并不整洁,也不是很甜美。但是哦,我很高兴现在得到功能。好推荐!!
再次感谢 Mick 提供的一些改进建议。
有 500 个错误有点有趣,因为当我决定将半通配符命名为 $half_wildcards 而不是 $wildcards_half 时,我搞砸了,我没有更新它们,哈哈。我现在已将其更改为 $halfwilds,因为我突然想到它,这与 $wildcards 和 $redirects 的字符数量相同,所以这是甜蜜的一致性。它也更加与众不同,这反过来又使事情变得不那么混乱。
这也带来了一个问题,如果有人使用它只是说$wildcards,或$redirects,或者在我的情况下,两者都有,但不是$halfwilds..关联的数组没有得到如果不存在重定向则创建,这将导致 500。所以我创建了空数组,因此它们将始终存在并且不会导致错误。
更新了脚本,稍微移动了数组键变量分配,因此如果您没有将它们设置为忽略未定义数组和变量等的警告,它们不会向日志发送垃圾邮件。我现在将这些日志设置为关键,因为它很烦人,但在这里对这个脚本懒惰。在意识到嵌套函数仍然可以很好地作为全局定义它们时,还将editkeys函数名称编辑为redir_editkeys。 grr php 有它的怪癖。