Error TOO MANY REDIRECTS debbuged - php

I'm spending a few hours trying to solve this ERR_TOO_MANY_REDIRECTS without success.
It happens when I access my website URL without being logged in. So if I do not have a session started I will be redirect to -> mywebsite.com/site/login or just /login
The PHP code that makes that is below:
if ( isset($_GET['p2k_url']) && $_GET['p2k_url'] ) {
if ( strstr($_GET['p2k_url'], '/') ) {
$url = explode('/', $_GET['p2k_url']);
} else {
$url[0] = $_GET['p2k_url'];
}
if ( !isset($url[1]) || !$url[1] ) {
$url[1] = 'index';
}
}
if ( $url[0] != 'login' && !$__usuCod ) {
header('Location: /site/login.php');
die();
}
if ( file_exists(SITE_DIR.DS.'_'.$url[0].DS.$url[1].'.php') ) {
include SITE_DIR.DS.'_'.$url[0].DS.$url[1].'.php';
} else {
if ( file_exists(SITE_DIR.DS.'_'.$url[0].DS.'no404.php') ) {
include SITE_DIR.DS.'_'.$url[0].DS.'index.php';
} else {
include SITE_DIR.DS.'_404'.DS.'index.php';
}
}
Right here: if ( $url[0] != 'login' && !$__usuCod ) {
My login.php is just a simple html page with form. Nothing there to worry about.
Although my main .htaccess is below and I think it might have something there:
Options -indexes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ index.php?p2k_url=$1 [QSA,L]
</IfModule>
In order to debug and find the error, when I run tail -f access_log I get just simple access requests:
127.0.0.1 - - [01/Nov/2016:11:16:28 -0200] "GET /site/login.php HTTP/1.1" 302 -
Nothing coming on error_log tough.
Doing reseraches I see that is a very comum problem on WP - which is not the case here. Any ideas?
Thanks

So you're redirecting to /site/login.php which your rewrite changes to index.php?p2k_url=site/login.php
$url will be an array of ['site', 'login.php'] (i'd trim($x, '/') the string before exploding to be sure).
Then you test if $url[0] != 'login' which will always be true as [0] is site. You need to test if $url[1] != 'login.php' or trim the file extension from the string first.
if you want to allow /site/login and /login then you just need to work out a rule for that. If /site/xxx is always equal to /xxx then just remove the first array index from $url if $url[0] == 'site' (or normalise your url's properly)
A really useful debugging technique i used in my early days was var_dump or print_r along with die() or exit. Use something like die('xxx') and move it up and down your script to identify where the redirect is occuring, then print out the variables to see what they contain and check your comparing them correctly. It's a crude method, but it works

Related

PHP URL Param redirects - with wildcards/regex

I recently found this solution for doing php url variable to header location redirects.
It's so much more manageable compared to htaccess for mass redirects, however one thing I want to next work out, how I can use regex to achieve what you can do with htaccess where request/(.*) goes to destination/$1.
My grasping is on that you use preg_match or preg_replace or something. How can I achieve something like the below, preferably keeping it short like this if possible. (I know this is wrong btw, just for example sake).
preg_match($redirects['request(.*)'] = "$domain/destination/\1");
Basically to break it down, say I want to redirect doma.in/pics to domain.tld/pictures, I have htaccess redirect that to doma.in/index?req=pics, where index is the script file and req is the parameter used.
And then using the script I have a line like $redirects['pics'] = "$domain/pictures";, where $domain variable is tied to http://domain.tld.
That works great, however I want to take this a step further with regex and send anything pics/*stuff*, aka doma.in/index?req=pics/*stuff* to $domain/pictures/*stuff*.
Here's an example of how things look using this script for doing many redirects.
$redirects['request'] = "$domain/dest";
$redirects['request2'] = "$domain/dest2";
$redirects['request3'] = "$domain/dest3";
Even though I've linked the post at the top that I got the script I'm using, here's the code:
if(isset($_GET['req']) && isset($redirects[$_GET['req']])) {
$loc = htmlspecialchars($redirects[$_GET['req']]);
header("Location: " . $loc);
exit();
}
header("Location: $domain");
With the $redirects lines being included above this, which I have in included files.
This is a long read, plus it is messy way of doing this. See my accepted answer for a much better way to do this.
I thought that ltrim() was what I wanted, seeing on other answers that if for example I specify 0 as what to remove, 01 will become 1, 001 will become 01, and 10 will be left as 10, 100 as 100 and so on. However this was not turning out to be the case. and instead it would strip all instances of the stated characters. Though it wasn't doing it with the slash, so confused.
This however does it correctly:
if (strpos($get, $req) === 0) {
$get = substr($get, strlen($req));
}
return $get;
Thanks to this answer for this one liner.
All I'm doing here with this script is just assigning $redirects['request'] to the associated value, like with any other variable value assignments. And the $_GET['req'] already does the job to get well whatever the parameter is, so no complicated preg or regex or anything.
So with that substr(), we can take the $_GET['req'] and do the following:
$req = "pics/";
$get = $_GET['req'];
$wild = strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
$redirects["pics/$wild"] = "$domain/pictures/$wild";
This takes pics/*stuff* and removes the pics/ so the value of $wild equals just *stuff*, and so I just use that in the redirect to make a wildcard and taadaa.
This is completely functional, but let's make this even better to save remembering this code each time which is a fair bit.
Create a function like this above the redirects:
function wildcard($req) {
$get = $_GET['req'];
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
By calling wildcard('pics/');, the $req equals pics/.
We can use this in redirects like:
$req = "pics/";
$wild = wildcard($req);
$redirects[$req.$wild] = "$domain/pictures/$wild";
It's still a bit more than I hoped for, so the idea I've had is to call $req as a global in the function, like this:
function wild() {
$get = $_GET['req']; global $req;
return strpos($get, $req) === 0
? substr($get, strlen($req))
: $get;
}
And then do the redirect like:
$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.
Updated script
I've completely overhauled this script, now I have realised a lot more that this is all an array that we're doing here with each redirect just adding to it. Also I've learnt a lot more about functions, and it's now extremely portable while also doing a lot more.
Here is the full new script. It's a beast compared to the previous, but the previous was so messy.
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.
}
We call this script by:
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.
)
);
To do simple redirects, we can do:
$redirects['request1'] = "$domain/dest1";
$redirects['request2'] = "$domain/dest2";
To do wildcards, we can do: (make sure to add trailing slashes on the end unless it's a destination such as as a query string)
$wildcards['request3'] = "$domain/dest3/";
$wildcards['request4'] = "$domain/dest4/";
And I also have added a half wildcards, so if you want to send request5/anypath to just $domain/dest5, and not dest5/anypath, we can do:
$halfwilds['request5'] = "$domain/dest5";
$halfwilds['request6'] = "$domain/dest6";
Let's split this into chunks and take a look at what each part is doing:
Configuration:
First we start the redirects(); function with the $config array as the argument. Then we assign variables to each setting.
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
We have two variables for the referer, one for the referer value, and the second to join up as a full param for use in the redirects.
Referer check
I've firstly included a check for if this script's referer param exists in the request, and just simply say "Do not loop back to the script!", and then exit(); the script.
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
}
The arrays and includes
Next up, if there is no match for the referer param in the request, we open an if for when the req param exists and is not empty, create the empty arrays, and then include where we have stated in the config we're putting our redirects.
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
}
From my understanding with the way php works, this actually has a benefit putting the includes inside the if, that if the condition isn't met, which would be the case when the request has no req param, the includes won't even get processed.
Leading & Trailing slashes
With how things were before with the previous script, we had to make sure we added slashes at the end of the redirect keys, and send requests to the script with trailing slashes at the end of the param. Let's take the need away from doing this by using trim(); for if it exists mixed with adding it back on, plus a leading slash too to ensure strpos(); won't match 'cat-dog/' when we wanted to look for '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
}
Here we've created a function called editkeys(); which makes a new array of the keys of whatever array you pass to it, does a foreach to modify those keys and then put them back into the original array, replacing the original keys.
Destination domain check for if referer param is needed
If we are sending the destination's 404 requests to the script, we want to stop redirect loops for redirects to that destination that end in 404s. We could just have the referer param to always be added, but that could risk bugging something up depending on that destination's website configuration's handling of query strings. So let's do a function to check for whether the passed destination goes to $domain, add the referer to it if true and return it back.
// 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
}
Redirecting
Next we have the part that puts together the redirects. Firstly we have the simple redirects. Firstly, we run the $redirects array though the editkeys(); function, then it checks if the matching key is in the array, run the referer(); function above on the destination and then redirect to it.
// 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();
}
Secondly is the wildcards. We run the $wildcards array through the editkeys(); function, run a foreach(); on the array to look for a matching key, get everything after the match as $wild, get only the match as $req, check the $req value exists as a key in the array, get that key's destination, attach the $wild on, then run the check for if referer is needed, redirect and 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();
}
}
}
Then we have half wildcards, which does more or less the same. I've not really got any real reason for this one myself, but there are reasons for it for sure, such as that you've got rid of a whole portfolio gallery and want to send requests to that and sub requests to the images etc back to the portfolio, this will do the job. So it's an included part of the script.
// 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();
}
}
}
I did want to try to do a function to save this largely duplicated code, but foreach();'s are darn awkward.
404
Then we have the 404 redirect that sends back home whatever requests to the script that either have no match with the request as a req param, or just with the referer param if there was no req param or if it is empty.
// 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.
}
And that's the script.
Now, to send dead requests to the script.
Apache / Litespeed / Openlitespeed (htaccess)
At the bottom of your htaccess, add this:
############# 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
Add this in the server's (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;
}
}
#############
I'm using Nginx now, moving away from OpenLitespeed since a weird issue came up that Nginx didn't have at all. So been some fun figuring out Nginx conf way of doing things. One thing I noticed was that by rewriting extension requests to no extensions, requests that get sent else where you'll notice have .php added on the end. So I've got it to exclude the extension in the rewrite here. Also doing these wildcard redirects in a location for error_page 404, is a tonne lot easier than trying to set in an if to ignore existent files/folders.
Removing the referer param on requests at the destination.
While trying to do the same with nginx what I'd done with htaccess, remove the referer param, which I was having fun trying to do, I realised that was a bit of a flawed solution anyway because it removes the whole query.
In comes using PHP instead, this function to achieve just that, removing a single param:
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'];
This function we can give props to this person for.
This is what lead me to just start cloning the way it was commented. It is such a tidy, readable way to do things. And even though my script before was short, it wasn't tidy, and it wasn't exactly sweet. But oh I'm so glad to get functions now. Well recommended!!
Thanks Mick for again the few tips for improving that bit more.
Had a bit of fun with 500 errors because I botched up when I decided to name the half wildcards $half_wildcards instead of $wildcards_half, I didn't update all of them lol. I've changed this now to $halfwilds, as I suddenly thought of it, which is the same amount of characters to $wildcards and $redirects so that's sweet consistency there. It differentiates it more too, which in turn just makes things less confusing.
Also this brought up the one problem that would arise if someone used this just say for $wildcards, or $redirects, or in my case, both, but not $halfwilds.. the associated array doesn't get created if no redirects for it exist, which would cause a 500. So I've created the empty arrays so they will always exist and not cause an error.
Updated the script a slight moving the array key variable assignations around so they don't spam the logs if you don't have them set to ignore warnings for undefined arrays and variables etc. I've got those logs now set to critical, because it is annoying but not here to be lazy with this script. Also edited the editkeys function name to redir_editkeys upon realising nested functions still darn well act as global defining them wise. grr php has it's quirks.

PHP Redirect to different URLs based on Parameters

I'm currently using this simple redirect (which passes all URL parameters to the next page) to redirect a link:
<?php
function preserve_qs() {
if (empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['REQUEST_URI'], "?") === false) {
return "";
}
return "?" . $_SERVER['QUERY_STRING'];
}
header("Status: 301 Moved Permanently");
header("Location: https://example.com/" . preserve_qs());
?>
One of the issues is that I have with this method is that I need to create a separate file for each redirect.
Is it possible to make this into something that I simply add different URLs inside and based on URL parameter that I call, it sends people to the right URL.
For example, in PHP, we store 3 URLs and we assign them 3 values (parameters):
example1.com = page1
example2.com = page2
example3.com = page3
and the PHP file URL would look like this:
example.com/redirect.php?land=page1?restofparameters
keep in mind that the rest of the parameters need to be sent to the goal page, but not the page1 parameter which calls the URL inside the PHP file.
So the target URL that people will land will would look like this:
example1.com/?restofparamaters
Any help is appreciated. Thank you!
you can try .htaccess method... like this...
In .htaccess file
RewriteEngine On
RewriteRule ^test/(1)? http://triviamaker.com [R=301,L]
then for check this one
localhost/your_project_folder/test/1
Note:- that .htaccess file must be in Root directory of your Project.
& if you have any query or found any problem related to that .htaccess method then you can Search "redirect a specific url to another url with htaccess" in Google. you will Found more details easily about this...
hope this one is Helps to you... Thank You...
I would recommend a link parser.
But here goes an example based on your code for stripping and inheriting GET URL parameters.
<?php
function preserve_qs() {
if (empty($_GET)) return '';
return '?'.http_build_query(array_diff($_GET, ['land']));
}
http_response_code(301);
header('Location: https://example.com/' . preserve_qs());
exit;
?>
I write this in test.php ... just for your Reference
Run This File for check Output...
http://localhost/url_rewrite/test?2
and run also like this http://localhost/url_rewrite/test?land=2
echo $temp = $_GET['land'];
echo $temp = $_SERVER['QUERY_STRING'];
if($temp == "1" || $temp == "land=1"){
header('Location: https://example.com');
}else if($temp == "2" || $temp == "land=2"){
header('Location: https://gmail.com');
}else if($temp == "3" || $temp == "land=3"){
header('Location: https://apple.com');
}else if($temp == "4" || $temp == "land=4"){
header('Location: user/2');
}
I hope this helps to you... Thank you

htaccess rewrite with subdomain as variable

I have a sitename.net and in a root directory i have .htaccess and index.php
.htaccess is:
FallbackResource /index.php
so basically as it's empty site (no sub directories, no files etc...) I will get a fallback to index.php which contains this:
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
echo "Domain is: $domain <br>";
if(empty($elements[0])) { // No path elements means home
echo "ShowHomepage()";
}
else switch(array_shift($elements)) { // Pop off first item and switch
case 'tests':
echo "First is test";
case 'sample':
echo "First is sample";
default:
header('HTTP/1.1 404 Not Found');
Show404Error();
}
my problem is that when visitor enters: https://username.sitename.net/tests/test1
I get error as subdomain doesn't exist...
When I go to "https://sitename.net/tests/test1" i get what I want but I need username as a variable as well.
Should I first do rewrite in .htaccess so it translate https://username.sitename.net/tests/test1 as https://sitename.net/username/tests/test1 and than redo index.php so it pickup a first array element as username or there is another option ?
Can somebody help me out ?
------------- EDIT ----------------
I've ended up pointing A record *.sitename.net to server IP
I've changed .htaccess so it's:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(.*)\.sitename\.net
RewriteRule ^(.*)$ subdomains/%1/$1 [L,NC,QSA]
FallbackResource /index.php
...and still getting 404 error... still can't get:
https://username.sitename.net/tests/test1 to act like https://sitename.net/username/tests/test1 so index.php will do it stuff...
I think wildcard DNS records is what you're looking for.
https://en.wikipedia.org/wiki/Wildcard_DNS_record
All subdomains will then redirect to your DNS, which you can redirect to your server.
EDIT:
Once the subdomains are up and running, you can use
.htaccess rewrite subdomain to directory
to fix the htaccess.
This work with php redirect too:
$url = "https://gbr8295.sitename.net"; //$_SERVER['HTTP_HOST']
if (substr($_SERVER['HTTP_HOST'], 0, 16) != 'https://sitename') { // You need edit 16 to a correct number for your domain
$username = substr($url, 8, ((strpos($url, '.') - 8)));
$new_url = "https://sitename.net/".$username."/";
echo $url."<br>"; // Output: https://gbr8295.sitename.net
echo $new_url; // Output: https://sitename.net/gbr8295/
header("Location: $new_url");
exit;
} else {
echo 'ok';
}

Rewriting URL's from a PHP Redirection

How can i rewrite this url:
http://localhost/?=register
To look like this?:
http://localhost/index.php/Register
Your redirection code:
header('Location: /index.php/Register/',true,302);
exit;
For accessing the /Register/ value, use:
$_SERVER['PATH_INFO']
After performing the redirection using the header command, you must remember to write your code to process that URL.
/index.php/Register will try to load a "Register" file inside "/index.php/" folder ... 404 error
So you will need to use apache modrewrite to redirect these "virtual folders" to a centralized script that can handle it.
Something like this on .htaccess:
RewriteEngine on
RewriteRule ^index.php/(.*)$ index.php
Then, at your index.php, you will treat the incomming URL to detect that file, and do whatever you want with it.
I usually work with a catch-all (redirects everything to /index.php) and then break the URL and treat it, so I can have any number of virtual folder/files. Here is my own function to treat any incoming request:
function extractUri($uri="") {
if ($uri == "") $uri = isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] != "" ? $_SERVER['REQUEST_URI'] : "";
if ($uri != "") {
# removes query from request
if ($uri[0] != "/") $uri = "/".$uri; # ALWAYS START WITH /
$uri = explode("?",$uri);
$uri = str_replace("..",".",array_shift($uri)); # little exploit remover
$uri = explode("/",str_replace("//","/",$uri));
} else
$uri = array("/");
$context = array();
foreach ($uri as $part)
array_push($context,preg_replace("/(\.){2,}/","\.",$part)); # prevents ..
$action = array_pop($context); # file (with extension)
$original_action = $action; # preserve the original file with extension (I work w/o them)
$ext = "";
if ($action == "") $action = 'index'; # so if you are accessing folder/, then you probably want the index
else if (strpos($action,".")!==false) { # remove extension
$action = explode(".",$action);
$ext = array_pop($action);
$action = implode(".",$action);
$action = removeSimbols($action,true,false); # makes sure it is a valid filename, this function removes any weird character
}
return array($context,$action,$original_action,$ext); # returns the folder structure (array), the page/action, the page/action with extension, and said extension (lots of repetition to speed up later)
}
so extractUri("/index.php/Register") would return:
Array ([0] => "/", [1] => "index.php"), "Register", "Register", ""

Change URL Extension from given URL [duplicate]

This question already has answers here:
How to get host name from this kind of URL?
(2 answers)
Closed 8 years ago.
Is there any way to accept a URL and change it's domain to .com ?
For example if a user were to submit www.example.in, I want to check if the URL is valid, and change that to www.example.com. I have built a regex checker that can check if the URL is valid, but I'm not entirely sure how to check if the given extension is valid, and then to change it to .com
EDIT : To be clear I am not actually going to these URL's. I am getting them submitted as user input in a form, and am simply storing them. These are functions I want to do to the URL before storing, that is all.
Edit 2 : An example to make this clearer -
$url = 'www.example.co.uk'
$newurl = function($url);
echo $newurl
which would yield the output
www.example.com
Are you looking for something like this on the server side to replace a list of selected TLDs to be translated to .coms?
<?php
$url = "www.example.in";
$replacement_tld = "com";
# array of all TLDs you wish to support
$valid_tlds = array("in","co.uk");
# possible TLD source lists
# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
# https://wiki.mozilla.org/TLD_List
# from http://stackoverflow.com/a/10473026/723139
function endsWith($haystack, $needle)
{
$haystack = strtolower($haystack);
$needle = strtolower($needle);
return $needle === "" || substr($haystack, -strlen($needle)) === $needle;
}
foreach($valid_tlds as $tld){
if(endsWith($url, $tld))
{
echo substr($url, 0, -strlen($tld)) . $replacement_tld . "\n";
break;
}
}
?>
Create an empty text file using a text editor such as notepad, and save it as htaccess.txt.
301 (Permanent) Redirect: Point an entire site to a different URL on a permanent basis. This is the most common type of redirect and is useful in most situations. In this example, we are redirecting to the "mt-example.com" domain:
# This allows you to redirect your entire website to any other domain
Redirect 301 / http://mt-example.com/
302 (Temporary) Redirect: Point an entire site to a different temporary URL. This is useful for SEO purposes when you have a temporary landing page and plan to switch back to your main landing page at a later date:
# This allows you to redirect your entire website to any other domain
Redirect 302 / http://mt-example.com/
For more details : http://kb.mediatemple.net/questions/242/How+do+I+redirect+my+site+using+a+.htaccess+file%3F
The question is not entirely clear, I'm assuming you wish to make this logic on PHP part.
Here's useful function to parse such strings:
function parseUrl ( $url )
{
$r = "^(?:(?P<scheme>\w+)://)?";
$r .= "(?:(?P<login>\w+):(?P<pass>\w+)#)?";
$r .= "(?P<host>(?:(?P<subdomain>[\w\.\-]+)\.)?" . "(?P<domain>\w+\.(?P<extension>\w+)))";
$r .= "(?::(?P<port>\d+))?";
$r .= "(?P<path>[\w/]*/(?P<file>\w+(?:\.\w+)?)?)?";
$r .= "(?:\?(?P<arg>[\w=&]+))?";
$r .= "(?:#(?P<anchor>\w+))?";
$r = "!$r!";
preg_match( $r, $url, $out );
return $out;
}
You can parse URL, validate it, and then recreate from resulting array replacing anything you want.
If you want to practice regexp and create own patterns - this site will be best place to do it.
If your goal to route users from one url to another or change URI style, then you need to use mod rewrite.
Actually in this case you will end up configuring your web server, probably virtual host, because it will route only listed domains (those being parked at the server).
To validate a URL in PHP You can use filter_var() .
filter_var($url, FILTER_VALIDATE_URL))
and then to get Top Level Domain (TLD) and replace the it with .com , you can use following function :
$url="http://www.dslreports.in";
$ext="com";
function change_url($url,$ext)
{
if(filter_var($url, FILTER_VALIDATE_URL)) {
$tld = '';
$url_parts = parse_url( (string) $url );
if( is_array( $url_parts ) && isset( $url_parts[ 'host' ] ) )
{
$host_parts = explode( '.', $url_parts[ 'host' ] );
if( is_array( $host_parts ) && count( $host_parts ) > 0 )
{
$tld = array_pop( $host_parts );
}
}
$new_url= str_replace($tld,$ext,$url);
return $new_url;
}else{
return "Not a valid URl";
}
}
echo change_url($url,$ext);
Hope this helps!

Categories