htaccess rewrite doesn't work as expected - php

I have an index.php file, with the following lines in it:
if(isset($_GET["page"]))
{
$page=$_GET["page"];
setcookie("page",$page,time()+315360000);
}
else if(isset($_COOKIE["page"]))
{
$page=$_COOKIE["page"];
}
else
{
$page="stock";
}
It's a simple page handler script, if you don't have the variables in your URL, the last viewed page will be opened.
Now I want to rewrite the URLs with a .htaccess file, and I have really strange results.
My webpage was hosted on a server like www.host.com/directory/index.php
Basically, I want the URLs look like www.host.com/directory/$page
The .htacces file was placed to the "directory", and have the following lines in it:
RewriteEngine on
RewriteRule ^(.*)$ index.php?page=$1 [NC]
My problem:
If the system can find a file based on the $page variable, it will be included. If the file doesn't exists, an error page will be displayed. Now, on the error page I echoed out the $page variable, and it is "index.php".
What is wrong with my code, and how can I fix it? I've never written any .htaccess before...
Thanks for your answers!

Your rule is looping, you need to add some conditions to prevent this from happening:
RewriteEngine on
RewriteCond $1 !^index\.php
RewriteRule ^(.*)$ index.php?page=$1 [NC]
or
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [NC]

Related

How to stop RewriteEngine/PHP redirect loop?

The task seems very simple:
all requests must be passed through one file.
However,
when following code is added to httpd.conf:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?route=$1 [QSA,R=301,L]
and following code is added to /index.php:
if( isset($_GET["route"]) && $_GET["route"] != "/index.php" ){
header("Location: ".$_GET["route"]);
}
then it causes redirect loop!
Causes for example such loop:
www.site.com/image.jpg -> (redirected by httpd.conf)
www.site.com/index.php?route=/image.jpg -> (redirected by index.php)
www.site.com/image.jpg -> (redirected by httpd.conf)
www.site.com/index.php?route=/image.jpg -> (redirected by index.php)
...
So, the question is following:
How to stop this loop?
To stop for example in such way:
www.site.com/image.jpg -> (redirected by httpd.conf)
www.site.com/index.php?route=/image.jpg -> (redirected by index.php)
www.site.com/image.jpg (no further redirection)
This one is a bit of patch, but I think it works.
httpd.conf:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{QUERY_STRING} !^(.*)a=a$ [NC]
RewriteRule ^(.*) index.php?route=$1 [QSA,L]
index.php:
<?php
if( isset($_GET["route"]) && $_GET["route"] != "/index.php" ){
header("Location: ".$_GET["route"].'?a=a');
}
The thing is: First time the rewrite engine redirects the page to index.php. Then, in index.php there's a redirection to the same file but adding parameter a=a. Then rewrite engine comes again, but he has orders of not redirect when found the string a=a in the query string, and there's no further redirection.
Of course this will end in a 404 error, since you're filtering only non-existant files with the first two rewritecond, but I guess you know how to deal with that.
Your rule looks fine but R=301 is a bit odd in your rule as you don't want to expose your internal URL in browser.
However PHP code is looking suspect due to this condition:
$_GET["route"] != "/index.php"
Which will always be true since /index.php itself will not be routed through this rule due to these conditions:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
Hence your code will cause a redirect loop by continuously redirecting using header function.
I suggest keep your rule like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php?route=$1 [QSA,L]
And your PHP code should just check presence of $_GET['route'] but should not do any redirects.
First, put this to .htaccess file, not in httpd.conf
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php [QSA,R=301,L]
Then, remove this redirect from your index.php file. You can get all your variables via $_GET or $_REQUEST.
What a senseless solutions. Of course it will cause redirect loop. In the RewriteCond-s you trying to catch files and dirs names that not exists in the server file system, and then you trying to pass their names to the index.php in which you make to request them again, again and again.
There is a single boilerplate that may come in handy, it should be placed on the top, after RewriteEngine on condition:
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !^[\s/]*$
RewriteRule ^ - [L]
An env was added, it works by theory, however I have tested it only once, see if it can solve the issue.
Why are you putting this:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?route=$1 [QSA,R=301,L]
In httpd.conf? You need to place this into file called .htaccess, create it into your root directory.

.htaccess doesn't redirect direct link to .php files

This is my current .htaccess file:
DirectoryIndex requestHandler.php
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ requestHandler.php?/$0 [L,QSA]
I want to redirect alle requests to "requestHandler.php". It works now, but it is also possible to access sites with the direct link, and I don't want that.
For example:
It now works with ".../api/register" , but you can also access it but going to ".../register.php" and that shouldn't be possible. It should only be possible to go to register.php by ".../api/register".
I think I had it working before, but as I continued editing I've seemed to mess it up.
requestHandler.php should be working properly and when I enter ".../register.php" it is not at all redirected to requestHandler, but if I enter ".../registe.php" or ".../register.ph" it is redirected there.
Any solutions?
The rule you posted is only checking if the file/directory exists, and if it doesn't, then redirect to requestHandler.php. So naturally, if an existing file is entered in the URL, it will not redirect.
If you want all ".php" files to get redirected as well, you'll need a more specific Rewrite rules. Something like this maybe:
DirectoryIndex requestHandler.php
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ requestHandler.php?/$0 [L,QSA]
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteRule ^(.*)$ requestHandler.php?/$0 [L,QSA]
You can probably consolidate that into one rule block, but at least this way it's very readable. The second rule block is only checked if the requested file is not a file or a directory.

add page name in the url using .htaccess

I just started .htaccess so I do not know too much about it, I try to google it but failed so I post my question here, I am sorry if the question is silly for you. My question is.
I use this code in .htaccess page:
RewriteEngine On
RewriteBase /learn/php/htaccess/
RewriteRule ^(.*)/(.*)$ index.php?n=$1&p=$2
when I enter this url:
http://localhost/learn/php/htaccess/page/number
it works fine. but I also want to add index.php (page name) in the url. I tried this:
http://localhost/learn/php/htaccess/index.php/page/number
AND
http://localhost/learn/php/htaccess/index.php?page/number
but failed. How can I do this?
I simply want to do that if I add another page then I am not sure but I have to use this code:
RewriteEngine On
RewriteBase /learn/php/htaccess/
RewriteRule ^(.*)/(.*)$ index.php?n=$1&p=$2
RewriteRule ^(.*)/(.*)$ another.php?x=$1&y=$2
but how can I open the another.php page with this format?
thanks
Try adding a few conditions to your rules:
RewriteEngine On
RewriteBase /learn/php/htaccess/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ index.php?n=$1&p=$2
As for routing to another page, you'll need to distinguish the difference between the two routes. For example, given a url:
http://localhost/learn/php/htaccess/foo/bar
where should it get routed to?
index.php?n=foo&p=bar
or
another.php?x=foo&y=bar
?
htaccess knows nothing about the content, only the URL and a regex pattern to match it, so unless you differentiate between the two, you can't route the same thing to two different scripts.
You can just make it easy like this
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?data=$1 [QSA]
in your index.php you put this code
$data = explode("/",$_GET['data']);
$page = $data[0];
$number = $data[1];

Passing URL with htaccess

htaccess below diverts PDF calls to validate.php where name of the PDF is get with $_GET['filename']
Problem is, it works with URLs below but it doesn't when there are many sub directories so what I need is, instead of just getting name of the file, I should pass whole URL to validation.php something like ^(.*)$ /validate.php?request_url=$1 [L] (this is just an example).
Note: instead of whole URL, anything after domain is acceptable.
WORKS:
http://www.whatever.com/1.pdf
http://www.whatever.com/2.pdf
http://www.whatever.com/3.pdf
WON'T WORK:
http://www.whatever.com/sub1/1.pdf
http://www.whatever.com/sub1/sub2/1.pdf
http://www.whatever.com/sub1/sub2/sub3/1.pdf
How can I do it?
Thanks
CURRENT HTACCESS:
RewriteEngine On
RewriteCond %{REQUEST_URI} \.(pdf)$ [NC]
RewriteRule ^(.*)$ /validate.php?filename=$1 [L]
CURRENT VALIDATION.PHP
if (isset($_GET['filename']))
{
//Do something with it
}
else
{
//Don't do anything
}
Try:
RewriteEngine On
RewriteCond %{REQUEST_URI} \.(pdf)$ [NC]
RewriteRule ^ /validate.php?filename=%{REQUEST_URI} [L]
Try this:
RewriteRule ^(.*)\.pdf$ /validate.php?filename=$1 [L]
without the RewriteCond

MOD_REWRITE & PHP $_SERVER['REQUEST_URI'] ISSUE

** UPDATED EXAMPLE **
For example, lets say my website url is "http://www.mydomain.com".
The site uses $_GET variables to determine pages, content etc.
So, let's say i'm on http://www.mydomain.com/cms/index.php?p=about-us
This would be the about us page within the CMS.
If I echo out $_SERVER['SERVER_NAME'] here, I get "http://www.mydomain.com"
If I echo out $_SEVER['REQUEST_URI'], I get "cms/index.php?p=about-us".
So, with the code below, the "$lastPage" gives me:
"http://www.mydomain.com/cms/index.php?p=about-us", this is exactly what I want.
BUT, as soon as I submit a form, or update content, etc, i'm being redirected to a css file, or an image path.
This ONLY happens when I have the rewrite rule in the htaccess file, which I need in order to have nicely formatted urls.
ORIGINAL QUESTION
I am running a website on a CMS, and within the CMS there is a "last page" variable. This variable is created like this:
$lastPage="";
$lastPage .= $_SERVER["SERVER_NAME"];
$lastPage .= $_SERVER["REQUEST_URI"];
$_SESSION['theLastPage'] = $lastPage;
The variable is used to redirect users to the last page they were on after updating content, submitting forms etc.
It is used like this:
<script>window.location="<?php echo $_SESSION['theLastPage']; ?>"</script>
This works exactly how I want it to...
Until I add this rewrite rule in my htaccess file:
RewriteRule ^([^/]+)\.html$ index.php?p=$1 [L]
As soon as that line is in my htaccess file, the redirect variable breaks, and directs the user to a css file, or image. The rewrite rule works as it should, and it is there in order to use nicely formatted urls throughout the website.
I've been trying to troubleshoot this for the last few days but have had no success.
If anyone could shed some light onto this for me, that'd be awesome.
Thanks!
HTACCESS FILE **
I can't explain the issue fully, because I don't understand why it's happening.
Here's my current htaccess file, there are a few different rewrite rules here, but the first one is the one that's causing the problem.
Options -Indexes
Options -MultiViews +FollowSymLinks
RewriteCond %{HTTP_HOST} !^www.yoursafetyexperts.com$
RewriteRule ^(.*)$ http://www.yoursafetyexperts.com/$1 [R=301]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/cms/
RewriteRule ^(.+) - [PT,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)\.html$ index.php?p=$1 [L] // If I remove this rule, my redirect works properly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/.]+)/([^/.]+)\.php$ index.php?p=$1&post_id=$2&post=$3 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/.]+)/([^/.]+)/$ index.php?p=$1&catId=$2&catName=$3 [L]
</IfModule>

Categories