我最近找到了這個解決方案,用于將 php url 變數設定為標頭位置重定向。
與用于批量重定向的 htaccess 相比,它更易于管理,但是我接下來要解決的一件事是,我如何使用正則運算式來實作您可以使用 htaccess 執行的操作,其中 request/(.*) 轉到目的地/$1。
我的理解是您使用 preg_match 或 preg_replace 或其他東西。我怎樣才能實作以下目標,如果可能的話,最好保持簡短。(順便說一句,我知道這是錯誤的,只是為了舉例)。
preg_match($redirects['request(.*)'] = "$domain/destination/\1");
基本上把它分解,說我想重定向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";
盡管我已經在頂部鏈接了我正在使用的腳本的帖子,但代碼如下:
if(isset($_GET['req']) && isset($redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . $loc);
exit();
}
header("Location: $domain");
上面包含 $redirects 行,我在包含的檔案中。
uj5u.com熱心網友回復:
這是一篇長文。有關更直接的要點版本,請參閱我接受的答案。
我認為這ltrim()就是我想要的,在其他答案中看到,例如,如果我指定 0 作為要洗掉的內容,則 01 將變為 1,001 將變為 01,10 將保留為 10,100 將保留為 100,依此類推。然而事實并非如此。相反,它會洗掉指定字符的所有實體。雖然它沒有用斜杠來做,但很困惑。
然而,這是正確的:
if (strpos($get, $req) === 0) {
$get = substr($get, strlen($req));
}
return $get;
感謝這個班輪的答案。
我在這里用這個腳本所做的只是分配$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 的值等于 just *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();
That becomes a much shorter single line. Though with the conflict around using globals, I've just put it back to as before but instead of repeatedly assigning $wild, just put $req back inside wild() and have it be like:
$req = "pics/"; $redirects[$req.wild($req)] = "$domain/pictures/".wild($req);
It's still shorter anyway and isn't much to it over the brackets being empty.
P.S, This method, you want to include the trailing slash on the parameter so results don't get messy.
In order to achieve to be able to send pics to the $domain/pictures, we want to have a trailing slash at the end of the parameter. In your redirect rule in htaccess to send requests as a parameter to the script, add a trailing slash on the end. So if you're using Apache or Litespeed, you can do the following in htaccess to send all requests to your script as a parameter with the trailing slash like:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?req=$1/ [R=301,L]
Make sure this is at the bottom so it doesn't take priority over other rules.
Also added a precautionary rtrim() to the script to remove the trailing slash in the header location, so if you want to link anything that doesn't remove trailing slashes on file links, it doesn't go to a dead link. As again the slashes weren't being effected by what behaviour I discovered as mentioned at top, this is fine here.
Here is how you can have things now.
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");
Now, this has one flaw if the destination is sending non existent requests to the script, if a destination, which is going to be guaranteed with wildcards, is non existent for the request, well.back it goes to the script and bam you have a redirect loop.
My way of solving this is to add ?referer=doma.in to the end of the header location, and in the htaccess on domain.tld, exclude non existent requests with that query string from redirecting back to the script.
So that looks like:
$loc = htmlspecialchars($redirects[$_GET['req']]).'?referer=doma.in';
And in the htaccess of domain.tld, place a rewritecond above the existing rule like so to exclude the query string:
# 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=$1/ [R=301,L]
For good measure I also added a referer on the redirect for the domain.tld.
Now, as a bonus, to hide the refer query on requests to tidy things up, let's add below:
# 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=$1 [R=301,L]
# Remove referer query from requests
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) /$1/? [R=301,L]
We need to send dead referer query requests somewhere before we remove the query, otherwise we'd be back at step one. I have the dead requests sent to my homepage with the request uri as a parameter so that can still know what the request url was.
And job done. But as an extra bonus, let's make external/non wildcard redirects not have a query. So back in the script, change the script to be like so:
$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();
}
Here, I've moved things about with the $_GET['req'] assigned to $get, $redirects[$get] assigned as $loc, $wildcards[$get] assigned to $wildloc, and call them in the issets, along with an extra isset after an :, aka OR for $wildloc.
And then have an if statement so $wildcards redirects use $loc assigned to $wildloc, and $redirects ones use the above one.
This way, we can have tidy redirects.
So now things look like:
// 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");
This improves things so much and solves the redirect loop.
Edited this again slightly as what I did here with the query string being appended.. the rtrim() therefore was looking for a non existent trailing slash after that, not where we wanted it to be doing it, before. So now the rtrim() comes before. Doubles it up which is slightly annoying but at least it does the job right now.
uj5u.com熱心網友回復:
由于我的另一個答案非常長,這是一個 TLDR 版本。
這是現在的腳本:
// 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
// Run Script
$get = $_GET['req'];
$loc = $redirects[$get];
$wildloc = $wildcards[$get];
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");
我們在這里做什么:通配符函式$req從請求引數中洗掉的值。我們在像wild($req);.
接下來例如清酒,$domain系結到http://domain.tld.
然后我們有重定向。這是兩個通配符重定向和一個非通配符重定向。確保在$req值的末尾有一個斜杠,否則會導致使用通配符的災難性結果。
接下來,我們已經$get分配到$_GET['req'],并且有$loc和$wildloc相應的分配$requests[$get]和$wildcards[$get]。
然后我們有一個 if 陳述句檢查是否有?req=引數,是否有匹配的$redirects['...'],或匹配的$wildcards['...']。
在里面,我們有另一個 if 陳述句要分配$loc給wildloc,用于rtrim()洗掉尾部斜杠,并在末尾添加一個?referer=doma.in查詢字串。
然后我們rtrim()再次在 $loc 上使用,所以如果它$wildloc變成了$loc,那么它會忽略,但如果它是原始的$loc,則洗掉尾部斜杠。我們也使用htmlspecialchars(),當我們不將用戶添加的請求引數字串列印到頁面上時,我不確定是否真的需要它,但我已經添加了以防萬一。
然后我們有標頭位置,將請求定向到關聯的位置。
如果沒有匹配項,我們將主頁重定向到http://domain.tld?req=request.
對于 doma.in 的 htaccess,我們在最后有:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /?req=$1/ [R=301,L]
這會指引http://doma.in/request到http://doma.in/?req=request/與結尾的斜線,并http://doma.in/request/folder以http://doma.in/?req=request/folder/
To prevent a redirect loop when there's guaranteed dead requests with wildcards and the destination domain.tld is redirecting dead requests back to the script, let's add to the bottom of domain.tld htaccess the below lines so that it will not send dead requests with ?referer=doma.in parameters back to the script, but home instead.
# Ignore these referer queries
RewriteCond %{QUERY_STRING} !referer=doma.in [NC]
# Send dead requests to hwl.li with uri as query
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://hwl.li/?referer=domain.tld&req=$1/ [R=301,L]
# Send dead requests with referer query to home
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) /?req=$1 [R=301,L]
# Remove referer query from requests
RewriteCond %{QUERY_STRING} "referer=" [NC]
RewriteRule (.*) /$1/? [R=301,L]
And this is all job done! Well Apache/Litespeed wise anyway.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/357809.html
上一篇:htaccess-重定向到錯誤頁面問題(帶斜線或不帶斜線)
下一篇:Nginx重定向動態頁面
