Apache PHP mod_rewrite not working - php

I'm trying to test out the mod_rewrite meaning:
I have two files: level1.php and warpzone.php.
In my .htaccess I have the following code:
RewriteEngine On
RewriteRule ^warp-zone.php$ level-1.php
Yet when I go to warpzone.php, nothing happens :/ (the url doesn't change)
Any suggestions? I really don't know what I'm doing wrong.

First of all you have dashes in php file names at your .htaccess file, while your files does not have them.
Rewrite conditions - this changes the content to new one, but URL stays as it was:
RewriteEngine On
RewriteRule ^warpzone\.php$ level1.php [L]
Redirect conditions - this changes both content and URL to new one:
RewriteEngine On
RewriteRule ^warpzone\.php$ /level1.php [R]
Also you can use Redirect condition instead of mod_rewrite:
Redirect 301 /warpzone.php /level1.php
In case if it does not work for you, you can use headers() method at the top of your warpzone.php file:
<?php
header("Location: " . $_SERVER['SERVER_NAME'] . "/level1.php");
?>

check whether warpzone.php or warp-zone.php is the correct filename, you are mixing them in your example.
check the apache error.log file if mod_rewrite is available, if not then enable it (this can be done either with "LoadModule ..." or it is wrapped by your Linux distribution)
check the apache error.log if you are allowed to use mod_rewrite, if not consider setting "AllowOverride All" in global config files httpd.conf/apache2.conf
change your rewrite rule to "RewriteRule ^warp-zone.php$ level-1.php [L]" to issue an http redirect; without L flag, is is handled internally in the web sever; see https://httpd.apache.org/docs/2.4/rewrite/flags.html for all flags
regards

Related

File being matched first instead of .htaccess rule

Whenever I have a file in my webserver and rewrite rule for the same path in my .htaccess, the rule is ignored and the file is automatically served.
I have only one file in the public_html of my webserver - test.php as follows:
<?php
echo "hello ".$_GET['action']
?>
Initially my .htaccess is empty and so visiting http://<domain-name>/test.php?action=world echoes hello world as expected. Also my webhost is so configured that visiting /test?action=world (with empty .htaccess) also echoes hello world.
Now I add the following .htaccess in public_html:
RewriteEngine On
RewriteRule ^test/(\w+)$ test.php?action=$1 [NC,L]
I expect that visiting /test/world will echo hello world, but that does not happen! I get only hello in the response. Now my initially thought is that mod_rewrite is not enabled, so to test that I change the .htaccess to:
RewriteEngine On
RewriteRule ^testmod/(\w+)$ test.php?action=$1 [NC,L]
Now to my surprise visiting /testmod/world actually echoes hello world! This shows that mod_rewrite is indeed available, and confirms that the rewrite rule is ignored when a file actually exists for the requested url.
My mental model is that Apache goes through the rules in the .htaccess, and for any rewrite rule matching the requested rule, Apache internally redirects to path specified in the rule. But that does happen here. It looks like first it checks if there exists any file for the requested url, and if not present, then look at the rewrite rules. Or something entirely else is happening here, maybe because of my webhost's configuration? (FYI, I'm using Bluehost as my webhost).
Add this to disable MultiViews:
Options -MultiViews
The Apache docs on mod_negotiation, describes what the Multiviews Option does, when enabled:
If the
server receives a request for /some/dir/foo and /some/dir/foo does not
exist, then the server reads the directory looking for all files named
foo.*, and effectively fakes up a type map which names all those
files, assigning them the same media types and content-encodings it
would have if the client had asked for one of them by name. It then
chooses the best match to the client's requirements, and returns that
document.
Use:
Options -MultiViews
RewriteEngine On
RewriteRule ^test/(\w+)$ test.php?action=$1 [NC,L]

htaccess rewrite rule not passing url vars when script file is same as rewrite directory

I'm trying to create nice urls with .htaccess files and have come across a weird issue.
I want to change portfolio.php?id=2 to /portfolio/2/
seems pretty simple solution
RewriteRule ^portfolio/([0-9]+)/$ /portfolio.php?id=$1 [L]
this does redirect to the correct script but when i try and run <?=$_GET['id'];?> it is undefined. but if change the script to something that does not equal the fake directory it works.
RewriteRule ^portfolio/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and just to make sure that it wasn't being caught by any other rules I tested this
RewriteRule ^portfolioitem/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and again it failed to pick up the id paramater!
any ideas?!
Cheers
This sounds suspiciously like a Multiviews related problem coupled with some PATH_INFO. The Multiviews option is part of mod_negotiation and it will try to match a requested URL path to a file path. It sees:
/portfolio/2/
And sees that there's a /portfolio.php file in the filesystem and assumes that this is what you want (which it is, but not in the same way). I'm willing to bet that instead of looking at $_GET['id'], which is blank of course since there are no GET params, if you look at $_SERVER['PATH_INFO'], you'll see it set to /2/. This is equivalent to going to:
/portfolio.php/2/
where the /2/ part gets passed to portfolio.php as part of the PATH_INFO. And since mod_negotiation is further up in the processing pipeline than mod_rewrite, your rewrite rules never get applied.
Try turning off multiviews. You can do this in your htaccess file using the Options directive (assuming your host has allowed Options):
Options -Multiviews

301 redirect in .htaccess for 30,000 errors

I've been tasked to clean up 30,000 or so url errors left behind from an old website as the result of a redesign and development.
I normally use .htaccess to do this, but I doubt it would be wise to have 30,000 301 redirects inside the .htaccess file!
What methods have some of you used to solve this problem?
Thanks in advance.
Here as you can do with apache httpd
RewriteMap escape int:escape
RewriteMap lowercase int:tolower
RewriteMap my_redir_map txt:map_rewrite.txt
RewriteCond ${my_redir_map:${lowercase:${escape:%{HTTP_HOST}%{REQUEST_URI}}}} ^(.+)$
RewriteRule .* http://%1 [R=301,L]
I use this rewrite rules usually directly inside apache httpd configuration.
Inside the map_rewrite.txt file you have a tab delimited file with the list of redirect in the following format:
www.example.it/tag/nozze www.example.it/categoria/matrimonio
www.example.it/tag/pippo www.example.it/pluto
www.example.it/tag/ancora www.google.com
Would be much easier if you can generalize the approach because the redirect have a common pattern. But if not, in this case you only need to add the redirected url into the list.
Take care to study the RewriteMap configuration, because you can also write the list into a different format, for example like a database table.
Please pay attention to this: I have added escape and lowercase only because there are accents into the urls I need to write. If your urls doesn't have accents, you can remove both.
If you want implement these redirects in php, here the code you need:
<?php
$dest_url = "http://example.com/path...";
header("HTTP/1.1 301 Moved Permanently");
header("Location: ".$dest_url);
Create a PHP page to operate as a 404 handler. It should inspect the incoming URL, check if it should map from an old page to a new page, then issue a 301. If there is no mapping then present a 404.
Simply set this page as the 404 handler in your .htaccess and there you go. IIRC this is how Wordpress used to handle 'clean' URLs on IIS before IIS7 brought in URL rewriting without needing a 3rd-party dll.
I have made a redirect class that is on the 404 page that will check the database if there is a valid page to 301 redirect to and redirect it instead of giving the 404 page. If it can't figure that out, it marks it in the database as a 404 page, so it can be fixed later.
Thanks for help guys. I've carried out the suggested course of action from freedev but have created a separate config file within Apache.
Within the httpd.conf file I have added:
# Map settings
Include "conf/extra/map.conf"
The map.conf file:
RewriteEngine On
RewriteEngine on
RewriteMap url_rewrite_map txt:conf/map.map
RewriteCond ${url_rewrite_map:$1|NOT_FOUND} !NOT_FOUND
RewriteRule ^(.*) http://website.com/${url_rewrite_map:$1} [R=301]
The map.map file is formatted as:
/oldname/ /newname
I've added quite a few of the urls for the redirection and so far so good, it isn't having a massive impact on the server like it did when added to .htaccess

how to redirect to another page if file exist in root?

I'm trying to make a script to put on all my pages on my site saying if so and so file exist in the root directory ("/") it will auto redirect to it and if the file isn't there it does nothing.
I'm using this so i can set up a maintenance mode for the site so i can take it down while im working on it. I already have made the maintenance page, I just don't know how to set up the script. The file name is maintenance.html and I only want it to be in the root file. I don't want to have to upload it to every directory to take the site down.
The file url would be http://domain.tld/maintenance.html and the script would go if the file is there and redirect to that file else if it's not there don't redirect.
I know the redirect code is (in HTML)
<meta HTTP-EQUIV="REFRESH" content="0; url=http://domain.tld">
You should try this in your .htaccess file:
RedirectPermanent / /maintenance.html
RedirectPermanent /page2.html /maintenance.html
RedirectPermanent /anotherpage.html /maintenance.html
And so on. So just do this for each page of your site, on a new line for each.
This will redirect each of your pages right away to the maintenance page.
.htaccess is the best way to do it in my opinion. (better than JavaScript)
Hope this helps.
EDIT:
To use it, first you put:
RedirectPermanent
And then a space and then the page you want to redirect to the maintenance page:
/page.html
And then another space and then the page you want to redirect to:
/maintenance.html
So, all together, here's an example:
RedirectPermanent /page.html /maintenance.html
Note the space in between RedirectPermanent, the page redirecting from and the page redirecting to.
The way it works, well I don't know. This isn't a script, it's a .htaccess file code.
You can use:
if(file_exists('/file.php'))
{
//do something if file exists
}
The better way would be the put a .htaccess named file in your root folder with the following content:
ErrorDocument 404 /maintenance.html
This redirects automatically to this page, if the called page is not existing.
A set of redirection rules for your webserver is what you need, methinks. If you're running Apache, mod_rewrite is the magic word, if you're running something else, well, then, I wouldn't know the magic word, but something similar exists for most servers, if not all.
But, using Apache's brilliant mod_rewrite, to redirect ALL traffic to a set page or address, e.g. during maintenance, is as simple as:
<IfModule mod_rewrite.c>
# Use mod_rewrite
RewriteEngine on
# If you want, you can exclude yourself by adding a condition for the redirection,
# i.e. if the RewriteCond matches, proceed with the RewriteRule
# This statement checks that the IP of the client isn't 123.456.789.012
RewriteCond %{REMOTE_ADDR} !123.456.789.012
# Redirect all traffic to /maintenance.html with a "307 Temporary Redirect",
# except traffic to the maintenance page.
RewriteCond %{REQUEST_FILENAME} !maintenance.html
RewriteRule .* /maintenance.html [R=307,L]
</IfModule>
Where should these instructions be, you ask? Well, since it's a temporary thing, the most logical would be in a .htaccess file in your webroot. But it's also possible to include the same in your servers/virtualhosts global configuration, which for a permanent ruleset would make sense from an optimization aspect.
To disable the redirection, it's enough to comment out either the RewriteEngine on statement, or the RedirectRule statement. You could also rename your .htaccess to something else or delete it.
It's not very efficient to write your own server-side script to check for a file when your webserver can do it for you. Use Apache's mod_rewrite capability in an .htaccess file; you'll enable (i.e. uncomment) your rewrite rules when you want to put your page in maintenance mode. Doing it this way would also allow you to access the website while you work on it if you put in a rule to allow access from your own IP.
If this is free hosting -- which it seems like it is -- then you may not be able to do this, but I don't see why it would be a major issue to do it. Most webserver software has some sort of rewrite function, and this is a fairly trivial rewrite.
Alternatively you could use a quick-and-dirty bit of Javascript similar to this (might not be exactly this):
<script type="text/javascript">location = www.yoursite.com/maintenance.html;</script>
It'd be better to use rewrites, though.

Run PHP code from .htaccess?

Say I have a rewrite that needs to pass the url to a PHP function and retrieve a value in order to tell what the new destination should be? is there a way to do that?
Thanks.
UPDATE:
Thanks so far guys..I am still having trouble but i'll show you my code:
.htaccess
#I got the file path by echoing DOCUMENT_ROOT and added the rest.
RewriteMap fixurl prg:/var/www/vhosts/mydomain.com/httpsdocs/domain_prototype/code_base/url_handler.php
RewriteEngine On
RewriteRule (.*) ${fixurl:$1} [PT]
PHP:
set_time_limit(0); # forever program!
$keyboard = fopen("php://stdin","r");
while (1) {
$line = trim(fgets($keyboard));
print "www.google.com\n"; # <-- just test to see if working.
}
However I am getting a 500 Internal Server Error I am not sure if there is an error in my .htaccess or in my PHP?
There is something called a RewriteMap.
You can call an executable script that will return the URL to rewrite to.
Check this article for more information and examples (in Perl, but are totally applicable to any other language):
http://www.onlamp.com/pub/a/apache/2005/04/28/apacheckbk.html
Summary of caveats:
Must run a read STDIN loop (ie, don't exit after receiving an URL)
Must print the URL to rewrite to WITH a trailing newline
Must be readable and executable by the user Apache runs as
This is the way to create the map
RewriteMap fixurl prg:/usr/local/scripts/fixit.php
And now we can use it in a RewriteRule:
RewriteEngine On
RewriteRule (.*) ${fixurl:$1}
EDIT: About the Internal Server Error. The most probable cause is what Gumbo mentions, RewriteMap cannot be used in .htaccess, sadly. You can use it in a RewriteRule in .htaccess, but can only create it in server config or virtual host config. To be certain, check the error log.
So, the only PHP / .htaccess only solution would be to rewrite everything to a certain PHP program which does the checking and redirects using the Location header. Something like:
RewriteRule (.*) proxy.php?args=$1 [QSA]
Then, in proxy.php
<?php
$url = get_proper_destination($QUERY_STRING); #args will have the URI path,
#and, via QSA you will have
#the original query string
header("Location: $url");
?>
Yes; you need a RewriteMap, of the External Rewriting Program variety.
What I would do is pass the URL to the PHP page and then do the final redirect using the PHP headers option.
header("Location: new-page.php");
If you didn't want it to redirect, you could also do an include of the page you want. I find that this is a little more flexible than using RewriteMap.
Hope this helps!
Note that the RewriteMap directive can only be used in the server config or virtual host context.

Categories