PHP URL 参数重定向 - wildcards/regex
PHP URL Param redirects - with wildcards/regex
我最近 found this solution 将 php url 变量重定向到 header 位置。
与用于大规模重定向的 htaccess 相比,它更易于管理,但是我接下来想解决的一件事是,我如何使用正则表达式来实现你可以用 htaccess 做的事情,其中 request/(.*) 到达目的地/$1.
我的理解是你使用 preg_match 或 preg_replace 或其他东西。我怎样才能实现类似下面的东西,如果可能的话,最好像这样保持简短。 (顺便说一句,我知道这是错误的,只是为了举例)。
preg_match($redirects['request(.*)'] = "$domain/destination/");
基本上是为了分解它,假设我想将 doma.in/pics
重定向到 domain.tld/pictures
,我让 htaccess 将其重定向到 doma.in/index?req=pics
,其中 index 是脚本文件,req 是使用的参数。
然后使用脚本我有一行 $redirects['pics'] = "$domain/pictures";
,其中 $domain
变量绑定到 http://domain.tld
。
效果很好,但是我想使用正则表达式更进一步,发送任何内容 pics/*stuff*
,也就是 doma.in/index?req=pics/*stuff*
到 $domain/pictures/*stuff*
。
下面是一个使用此脚本进行多次重定向的示例。
$redirects['request'] = "$domain/dest";
$redirects['request2'] = "$domain/dest2";
$redirects['request3'] = "$domain/dest3";
即使我已经在顶部链接了 post,我得到了我正在使用的脚本,这里是代码:
if(isset($_GET['req']) && isset($redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . $loc);
exit();
}
header("Location: $domain");
上面包含 $redirects 行,我在包含的文件中有这些行。
这是一篇很长的文章,而且这样做的方式很混乱。请参阅我接受的答案以获得更好的方法。
我认为 ltrim()
是我想要的,看到其他答案,例如,如果我指定 0 作为要删除的内容,则 01 将变为 1,001 将变为 01,而 10 将保留为10、100 为 100 等等。然而事实并非如此。相反,它会删除指定字符的所有实例。虽然不是用斜杠做的,所以很困惑。
但是这样做是正确的:
if (strpos($get, $req) === 0) {
$get = substr($get, strlen($req));
}
return $get;
Thanks to this answer for this one liner.
我在这里使用此脚本所做的只是将 $redirects['request']
分配给关联值,就像任何其他变量值分配一样。而且 $_GET['req']
已经完成了无论参数是什么都可以正常工作的工作,所以没有复杂的 preg 或 regex 或任何东西。
所以有了 substr()
,我们可以使用 $_GET['req']
并执行以下操作:
$req = "pics/";
$get = $_GET['req'];
$wild = strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
$redirects["pics/$wild"] = "$domain/pictures/$wild";
这需要 pics/*stuff*
并删除 pics/
所以 $wild 的值等于 *stuff*
,所以我只是在重定向中使用它来制作通配符和 taadaa。
这是完全可用的,但让我们让它变得更好,以节省每次记住这段代码的时间,这是很公平的。
在重定向之上创建这样的函数:
function wildcard($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
通过调用 wildcard('pics/');
,$req
等于 pics/
。
我们可以在重定向中使用它,例如:
$req = "pics/";
$wild = wildcard($req);
$redirects[$req.$wild] = "$domain/pictures/$wild";
它仍然比我希望的要多一点,所以我的想法是在函数中将 $req
作为全局调用,如下所示:
function wild() {
$get = $_GET['req']; global $req;
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
然后像这样进行重定向:
$req = "pics/";
$redirects[$req.wild()] = "$domain/pictures/".wild();
这变成了一条更短的单行。尽管由于使用全局变量的冲突,我只是把它恢复到以前的状态,而不是重复分配 $wild
,只是把 $req
放回 wild()
里面,让它像:
$req = "pics/"; $redirects[$req.wild($req)] = "$domain/pictures/".wild($req);
它仍然更短,而且括号是空的也没什么大不了的。
P.S,这个方法,你想在参数上包含尾部斜杠,这样结果就不会变得混乱。
为了实现能够将 pics
发送到 $domain/pictures
,我们希望在参数末尾有一个斜杠。在 htaccess 中将请求作为参数发送到脚本的重定向规则中,在末尾添加一个尾部斜杠。因此,如果您使用的是 Apache 或 Litespeed,则可以在 htaccess 中执行以下操作,将所有请求作为参数发送到您的脚本,并带有尾部斜杠,例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?req=/ [R=301,L]
确保它位于底部,这样它就不会优先于其他规则。
还在脚本中添加了一个预防措施 rtrim()
以删除 header 位置的尾部斜杠,因此如果您想要 link 任何不删除尾部斜杠的内容文件 links,它不会死掉 link。正如顶部提到的,我发现的行为不会影响斜线,这在这里很好。
这是您现在可以拥有东西的方法。
function wild($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
$domain = "http://domain.tld";
// Redirects
$req = "request1/"; $redirects[$req.wild($req)] = "$domain/dest1/".wild($req);
$req = "request2/"; $redirects[$req.wild($req)] = "$domain/dest2/".wild($req);
$req = "request3/"; $redirects[$req.wild($req)] = "$domain/dest3/".wild($req);
// Run Script
if (isset($_GET['req'], $redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . rtrim($loc,"/"));
exit();
}
// If no match in the redirects, redirect to this location.
header("Location: $domain");
现在,如果目标正在向脚本发送不存在的请求,这有一个缺陷,如果请求不存在将使用通配符保证的目标,well.back 它会到脚本和 bam 你有一个重定向循环。
我解决这个问题的方法是将 ?referer=doma.in
添加到 header 位置的末尾,并在 domain.tld 上的 htaccess 中,排除不存在的带有该查询字符串的请求重定向回脚本。
看起来像:
$loc = htmlspecialchars($redirects[$_GET['req']]).'?referer=doma.in';
并且在 domain.tld 的 htaccess 中,像这样在现有规则之上放置一个 rewritecond 以排除查询字符串:
# Ignore these referer queries
RewriteCond %{QUERY_STRING} !referer=doma.in [NC]
# Send dead requests to doma.in with uri as query
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://doma.in/?referer=domain.tld&req=/ [R=301,L]
为了更好的衡量,我还在 domain.tld.
的重定向上添加了一个引荐来源网址
现在,作为奖励,要隐藏对整理请求的引用查询,让我们在下面添加:
# Send dead requests with referer query to home (or 404 or wherever)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) /?req= [R=301,L]
# Remove referer query from requests
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) //? [R=301,L]
在删除查询之前,我们需要在某处发送死引用查询请求,否则我们会回到第一步。我将死请求发送到我的主页,请求 uri 作为参数,这样仍然可以知道请求 url 是什么。
工作完成。但作为额外的奖励,我们让 external/non 通配符重定向没有查询。所以回到脚本中,将脚本更改为:
$get = $_GET['req'];
$loc = $redirects[$get];
$wildloc = $wildcards[$get];
// Run Script
if(isset($get) && isset($loc) || isset($wildloc)) {
if(isset($wildcards[$get])) {
$loc = rtrim($wildloc,'/').'?referer=hwl.li'; }
$loc = rtrim(htmlspecialchars($loc),'/');
header("Location: ".$loc);
exit();
}
在这里,我将 $_GET['req']
分配给 $get
,$redirects[$get]
分配为 $loc
,$wildcards[$get]
分配给 $wildloc
,并在 issets 中调用它们,并在 :
之后添加一个额外的 isset,也就是 $wildloc
.
的 OR
然后有一个 if 语句,所以 $wildcards
重定向使用 $loc
分配给 $wildloc
,而 $redirects
则使用上面的。
这样,我们就可以进行整洁的重定向。
所以现在看起来像:
// Wildcard function
function wild($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
$domain = "http://domain.tld";
// Redirects
$req = "request1/"; $wildcards[$req.wild($req)] = "$domain/dest1/".wild($req); // A wildcard redirect
$req = "request2/"; $wildcards[$req.wild($req)] = "$domain/dest2/".wild($req); // A wildcard redirect
$redirects['request3/'] = "$domain/dest3/"; // Not a wildcard redirect
$get = $_GET['req'];
$loc = $redirects[$get];
$wildloc = $wildcards[$get];
// Run Script
if(isset($get) && isset($loc) || isset($wildloc)) {
if(isset($wildcards[$get])) {
$loc = rtrim($wildloc,'/').'?referer=hwl.li';}
$loc = rtrim(htmlspecialchars($loc),'/');
header("Location: ".$loc);
exit();
}
// If no match in the redirects, redirect to this location.
header("Location: $domain/?req=$get");
这大大改善了事情并解决了重定向循环。
像我在这里所做的那样再次稍微编辑它附加了查询字符串.. 因此 rtrim()
之后正在寻找一个不存在的尾部斜杠,而不是我们希望它这样做的地方,前。所以现在 rtrim()
出现在前面。双开始吧,这有点烦人,但至少它现在可以完成工作。
更新脚本
我已经彻底修改了这个脚本,现在我已经意识到这是我们在这里做的所有内容的一个数组,每个重定向只是添加到它。此外,我还学到了更多关于函数的知识,它现在非常便携,同时还能做更多事情。
这是完整的新脚本。和之前的比起来简直牛逼了,但是之前的太乱了。
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
我们有两个变量用于 referer,一个用于 referer 值,第二个作为完整参数连接起来用于重定向。
- 推荐人检查
我首先检查请求中是否存在此脚本的引用参数,然后简单地说 "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,创建空数组,然后包含我们在配置我们正在放置我们的重定向。
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 工作方式的理解,将 include 放在 if 中实际上有一个好处,即如果不满足条件,即请求没有 req 时的情况param,include 甚至不会被处理。
- 前导和尾部斜杠
根据之前脚本的情况,我们必须确保在重定向键的末尾添加斜杠,并在参数末尾使用尾部斜杠向脚本发送请求。让我们通过使用 trim();
来避免这样做,因为如果它存在并重新添加它,再加上一个前导斜线以确保 strpos();
在我们想要的时候不会匹配 'cat-dog/'寻找 'dog/'.
// 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 修改这些键,然后将它们放回原始数组, 替换原来的键。
- 目标域检查是否需要 referer 参数
如果我们将目标的 404 请求发送到脚本,我们希望停止重定向循环以重定向到以 404 结尾的目标。我们可以始终添加 referer 参数,但这可能会出现错误,具体取决于该目的地的网站配置对查询字符串的处理。因此,让我们做一个函数来检查传递的目标是否到达 $domain
,如果为真,则将引用添加到它,然后 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
}
- 重定向
接下来是将重定向组合在一起的部分。首先我们有简单的重定向。首先,我们通过 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();
}
其次是通配符。我们运行$wildcards
数组通过editkeys();
函数,运行一个foreach();
数组上去寻找匹配的key,得到匹配后的所有内容为$wild
,仅获取 $req
的匹配项,检查 $req
值是否作为键存在于数组中,获取该键的目标,附加 $wild,然后 运行检查是否需要 referer,重定向和 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 参数或它为空则仅与 referer 参数匹配.
// 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= [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= redirect;
}
}
#############
我现在正在使用 Nginx,不再使用 OpenLitespeed,因为出现了一个 Nginx 根本没有的奇怪问题。因此,弄清楚 Nginx conf 的做事方式很有趣。我注意到的一件事是,通过将扩展请求重写为无扩展,发送到您会注意到的其他地方的请求在末尾添加了 .php。所以我已经在此处排除了重写中的扩展名。此外,在 error_page 404
的位置执行这些通配符重定向比尝试在 if
中设置以忽略现有的 files/folders.
要容易得多
正在删除目的地请求的 referer 参数。
在尝试对 nginx 执行与我对 htaccess 相同的操作时,删除 referer 参数,我尝试这样做很有趣,但我意识到无论如何这是一个有缺陷的解决方案,因为它删除了整个查询。
In comes using 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 有它的怪癖。
我最近 found this solution 将 php url 变量重定向到 header 位置。
与用于大规模重定向的 htaccess 相比,它更易于管理,但是我接下来想解决的一件事是,我如何使用正则表达式来实现你可以用 htaccess 做的事情,其中 request/(.*) 到达目的地/$1.
我的理解是你使用 preg_match 或 preg_replace 或其他东西。我怎样才能实现类似下面的东西,如果可能的话,最好像这样保持简短。 (顺便说一句,我知道这是错误的,只是为了举例)。
preg_match($redirects['request(.*)'] = "$domain/destination/");
基本上是为了分解它,假设我想将 doma.in/pics
重定向到 domain.tld/pictures
,我让 htaccess 将其重定向到 doma.in/index?req=pics
,其中 index 是脚本文件,req 是使用的参数。
然后使用脚本我有一行 $redirects['pics'] = "$domain/pictures";
,其中 $domain
变量绑定到 http://domain.tld
。
效果很好,但是我想使用正则表达式更进一步,发送任何内容 pics/*stuff*
,也就是 doma.in/index?req=pics/*stuff*
到 $domain/pictures/*stuff*
。
下面是一个使用此脚本进行多次重定向的示例。
$redirects['request'] = "$domain/dest";
$redirects['request2'] = "$domain/dest2";
$redirects['request3'] = "$domain/dest3";
即使我已经在顶部链接了 post,我得到了我正在使用的脚本,这里是代码:
if(isset($_GET['req']) && isset($redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . $loc);
exit();
}
header("Location: $domain");
上面包含 $redirects 行,我在包含的文件中有这些行。
这是一篇很长的文章,而且这样做的方式很混乱。请参阅我接受的答案以获得更好的方法。
我认为 ltrim()
是我想要的,看到其他答案,例如,如果我指定 0 作为要删除的内容,则 01 将变为 1,001 将变为 01,而 10 将保留为10、100 为 100 等等。然而事实并非如此。相反,它会删除指定字符的所有实例。虽然不是用斜杠做的,所以很困惑。
但是这样做是正确的:
if (strpos($get, $req) === 0) {
$get = substr($get, strlen($req));
}
return $get;
Thanks to this answer for this one liner.
我在这里使用此脚本所做的只是将 $redirects['request']
分配给关联值,就像任何其他变量值分配一样。而且 $_GET['req']
已经完成了无论参数是什么都可以正常工作的工作,所以没有复杂的 preg 或 regex 或任何东西。
所以有了 substr()
,我们可以使用 $_GET['req']
并执行以下操作:
$req = "pics/";
$get = $_GET['req'];
$wild = strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
$redirects["pics/$wild"] = "$domain/pictures/$wild";
这需要 pics/*stuff*
并删除 pics/
所以 $wild 的值等于 *stuff*
,所以我只是在重定向中使用它来制作通配符和 taadaa。
这是完全可用的,但让我们让它变得更好,以节省每次记住这段代码的时间,这是很公平的。
在重定向之上创建这样的函数:
function wildcard($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
通过调用 wildcard('pics/');
,$req
等于 pics/
。
我们可以在重定向中使用它,例如:
$req = "pics/";
$wild = wildcard($req);
$redirects[$req.$wild] = "$domain/pictures/$wild";
它仍然比我希望的要多一点,所以我的想法是在函数中将 $req
作为全局调用,如下所示:
function wild() {
$get = $_GET['req']; global $req;
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
然后像这样进行重定向:
$req = "pics/";
$redirects[$req.wild()] = "$domain/pictures/".wild();
这变成了一条更短的单行。尽管由于使用全局变量的冲突,我只是把它恢复到以前的状态,而不是重复分配 $wild
,只是把 $req
放回 wild()
里面,让它像:
$req = "pics/"; $redirects[$req.wild($req)] = "$domain/pictures/".wild($req);
它仍然更短,而且括号是空的也没什么大不了的。
P.S,这个方法,你想在参数上包含尾部斜杠,这样结果就不会变得混乱。
为了实现能够将 pics
发送到 $domain/pictures
,我们希望在参数末尾有一个斜杠。在 htaccess 中将请求作为参数发送到脚本的重定向规则中,在末尾添加一个尾部斜杠。因此,如果您使用的是 Apache 或 Litespeed,则可以在 htaccess 中执行以下操作,将所有请求作为参数发送到您的脚本,并带有尾部斜杠,例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?req=/ [R=301,L]
确保它位于底部,这样它就不会优先于其他规则。
还在脚本中添加了一个预防措施 rtrim()
以删除 header 位置的尾部斜杠,因此如果您想要 link 任何不删除尾部斜杠的内容文件 links,它不会死掉 link。正如顶部提到的,我发现的行为不会影响斜线,这在这里很好。
这是您现在可以拥有东西的方法。
function wild($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
$domain = "http://domain.tld";
// Redirects
$req = "request1/"; $redirects[$req.wild($req)] = "$domain/dest1/".wild($req);
$req = "request2/"; $redirects[$req.wild($req)] = "$domain/dest2/".wild($req);
$req = "request3/"; $redirects[$req.wild($req)] = "$domain/dest3/".wild($req);
// Run Script
if (isset($_GET['req'], $redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . rtrim($loc,"/"));
exit();
}
// If no match in the redirects, redirect to this location.
header("Location: $domain");
现在,如果目标正在向脚本发送不存在的请求,这有一个缺陷,如果请求不存在将使用通配符保证的目标,well.back 它会到脚本和 bam 你有一个重定向循环。
我解决这个问题的方法是将 ?referer=doma.in
添加到 header 位置的末尾,并在 domain.tld 上的 htaccess 中,排除不存在的带有该查询字符串的请求重定向回脚本。
看起来像:
$loc = htmlspecialchars($redirects[$_GET['req']]).'?referer=doma.in';
并且在 domain.tld 的 htaccess 中,像这样在现有规则之上放置一个 rewritecond 以排除查询字符串:
# Ignore these referer queries
RewriteCond %{QUERY_STRING} !referer=doma.in [NC]
# Send dead requests to doma.in with uri as query
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://doma.in/?referer=domain.tld&req=/ [R=301,L]
为了更好的衡量,我还在 domain.tld.
的重定向上添加了一个引荐来源网址现在,作为奖励,要隐藏对整理请求的引用查询,让我们在下面添加:
# Send dead requests with referer query to home (or 404 or wherever)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) /?req= [R=301,L]
# Remove referer query from requests
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) //? [R=301,L]
在删除查询之前,我们需要在某处发送死引用查询请求,否则我们会回到第一步。我将死请求发送到我的主页,请求 uri 作为参数,这样仍然可以知道请求 url 是什么。
工作完成。但作为额外的奖励,我们让 external/non 通配符重定向没有查询。所以回到脚本中,将脚本更改为:
$get = $_GET['req'];
$loc = $redirects[$get];
$wildloc = $wildcards[$get];
// Run Script
if(isset($get) && isset($loc) || isset($wildloc)) {
if(isset($wildcards[$get])) {
$loc = rtrim($wildloc,'/').'?referer=hwl.li'; }
$loc = rtrim(htmlspecialchars($loc),'/');
header("Location: ".$loc);
exit();
}
在这里,我将 $_GET['req']
分配给 $get
,$redirects[$get]
分配为 $loc
,$wildcards[$get]
分配给 $wildloc
,并在 issets 中调用它们,并在 :
之后添加一个额外的 isset,也就是 $wildloc
.
OR
然后有一个 if 语句,所以 $wildcards
重定向使用 $loc
分配给 $wildloc
,而 $redirects
则使用上面的。
这样,我们就可以进行整洁的重定向。
所以现在看起来像:
// Wildcard function
function wild($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
$domain = "http://domain.tld";
// Redirects
$req = "request1/"; $wildcards[$req.wild($req)] = "$domain/dest1/".wild($req); // A wildcard redirect
$req = "request2/"; $wildcards[$req.wild($req)] = "$domain/dest2/".wild($req); // A wildcard redirect
$redirects['request3/'] = "$domain/dest3/"; // Not a wildcard redirect
$get = $_GET['req'];
$loc = $redirects[$get];
$wildloc = $wildcards[$get];
// Run Script
if(isset($get) && isset($loc) || isset($wildloc)) {
if(isset($wildcards[$get])) {
$loc = rtrim($wildloc,'/').'?referer=hwl.li';}
$loc = rtrim(htmlspecialchars($loc),'/');
header("Location: ".$loc);
exit();
}
// If no match in the redirects, redirect to this location.
header("Location: $domain/?req=$get");
这大大改善了事情并解决了重定向循环。
像我在这里所做的那样再次稍微编辑它附加了查询字符串.. 因此 rtrim()
之后正在寻找一个不存在的尾部斜杠,而不是我们希望它这样做的地方,前。所以现在 rtrim()
出现在前面。双开始吧,这有点烦人,但至少它现在可以完成工作。
更新脚本
我已经彻底修改了这个脚本,现在我已经意识到这是我们在这里做的所有内容的一个数组,每个重定向只是添加到它。此外,我还学到了更多关于函数的知识,它现在非常便携,同时还能做更多事情。
这是完整的新脚本。和之前的比起来简直牛逼了,但是之前的太乱了。
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
我们有两个变量用于 referer,一个用于 referer 值,第二个作为完整参数连接起来用于重定向。
- 推荐人检查
我首先检查请求中是否存在此脚本的引用参数,然后简单地说 "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,创建空数组,然后包含我们在配置我们正在放置我们的重定向。
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 工作方式的理解,将 include 放在 if 中实际上有一个好处,即如果不满足条件,即请求没有 req 时的情况param,include 甚至不会被处理。
- 前导和尾部斜杠
根据之前脚本的情况,我们必须确保在重定向键的末尾添加斜杠,并在参数末尾使用尾部斜杠向脚本发送请求。让我们通过使用 trim();
来避免这样做,因为如果它存在并重新添加它,再加上一个前导斜线以确保 strpos();
在我们想要的时候不会匹配 'cat-dog/'寻找 'dog/'.
// 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 修改这些键,然后将它们放回原始数组, 替换原来的键。
- 目标域检查是否需要 referer 参数
如果我们将目标的 404 请求发送到脚本,我们希望停止重定向循环以重定向到以 404 结尾的目标。我们可以始终添加 referer 参数,但这可能会出现错误,具体取决于该目的地的网站配置对查询字符串的处理。因此,让我们做一个函数来检查传递的目标是否到达 $domain
,如果为真,则将引用添加到它,然后 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
}
- 重定向
接下来是将重定向组合在一起的部分。首先我们有简单的重定向。首先,我们通过 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();
}
其次是通配符。我们运行$wildcards
数组通过editkeys();
函数,运行一个foreach();
数组上去寻找匹配的key,得到匹配后的所有内容为$wild
,仅获取 $req
的匹配项,检查 $req
值是否作为键存在于数组中,获取该键的目标,附加 $wild,然后 运行检查是否需要 referer,重定向和 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 参数或它为空则仅与 referer 参数匹配.
// 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= [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= redirect;
}
}
#############
我现在正在使用 Nginx,不再使用 OpenLitespeed,因为出现了一个 Nginx 根本没有的奇怪问题。因此,弄清楚 Nginx conf 的做事方式很有趣。我注意到的一件事是,通过将扩展请求重写为无扩展,发送到您会注意到的其他地方的请求在末尾添加了 .php。所以我已经在此处排除了重写中的扩展名。此外,在 error_page 404
的位置执行这些通配符重定向比尝试在 if
中设置以忽略现有的 files/folders.
正在删除目的地请求的 referer 参数。
在尝试对 nginx 执行与我对 htaccess 相同的操作时,删除 referer 参数,我尝试这样做很有趣,但我意识到无论如何这是一个有缺陷的解决方案,因为它删除了整个查询。 In comes using 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 有它的怪癖。