Rewrite rule to hide extension .htaccess - php

I am trying to hide the extension of .php file from the link
for example www.example.com/about.php
To display www.example.com/about
what I did
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
and It works perfectly.
but I have another link which example.com/news.php?id=45
according to the above rule, I can access the link like
example.com/news?id=45 without .php
but I want to hide id=45 I want it like this example.com/news/45
what I did RewriteRule ^news.php?id=([0-9]+) /news/$1 [NC,L]
But It won't work I got 500 Internal Server Error

Try it like this instead:
# MultiViews must be disabled for "/news/45" to work
Options -MultiViews
RewriteEngine on
# Rewrite "/news/45" to "news.php?id=45"
RewriteRule ^news/(\d+)$ news.php?id=$1 [L]
# Handle extensionless ".php" URLs
RewriteCond %{REQUEST_URI} !\.\w{2,3}$
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
Your 500 Internal Server Error was actually caused by your original directives that "hide" the .php extension, not your "new" directive (that wasn't actually doing anything). Your original directives would have rewritten a request for /news/45 to /news/45.php to /news/45.php.php etc. creating a rewrite-loop (500 error).
See my answer to the following question on ServerFault with a detailed explanation of this behaviour: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error
what I did RewriteRule ^news.php?id=([0-9]+) /news/$1 [NC,L]
But It won't work I got 500 Internal Server Error
The logic of this directive is reversed and would never actually match the requested URL (or anything for that matter), so won't actually do anything. It is, however, syntactically OK, so won't trigger an error.
The 500 error would have occurred simply by requesting /news/45 (with your original directives), whether this directive was in place or not.

Related

.htaccess mod_rewrite working ONLY with HTML, not with my PHP files

I've just finished setting up my first app on localhost - and the .htaccess working incredibly fine. I just uploaded the files to Google Cloud LAMP Server, set up the database & got everything working -- however, for some reason the PHP files are not being located (?) which is strange because it's working in localhost just fine, and HTML files seem to be rewrited just fine as well!
Here's the error log in apache:
Negotiation: discovered file(s) matching request: /var/www/html/index (None could be negotiated).
Here's my .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [NC,L]
What is strange is that it's rewriting HTML with no problem but PHP files will throw this:
Not Found
The requested URL was not found on this server.
I tried pretty much everything:
Changed /etc/apache2/apache2.conf
Changed /etc/apache2/sites-available/000-default.conf
Made sure that 'a2enmod rewrite' is enabled
Still, getting
Not Found
The requested URL was not found on this server.
If looks as if MultiViews is enabled, but .php files are not a permitted extension. MultiViews needs to be disabled for your mod_rewrite rules to be processed successfully. To disable MultiViews, add the following to the top of the .htaccess file:
Options -MultiViews
MultiViews is disabled by default, however, it is explicitly enabled (in the server config) on some distros.
Aside:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [NC,L]
The first condition that checks that the request does not map to a directory is entirely redundant.
The condition that checks whether the corresponding .php (or .html) file exists is not necessarily checking that the same "file" you are rewriting to. If, for instance, you requested /foo/bar and foo.php happened to exist then you will get a rewrite-loop (500 Internal Server Error). To resolve this issue, it should be rewritten like this instead:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
The NC flag was superfluous, as was the anchors surrounding the RewriteRule pattern.

htaccess - redirect to error pages issue (with slash or without slash)

There is an issue with redirection to error pages:
example.com/test - will redirect to 404 error page
but
example.com/test/ - will go to the white "File not found." page
to mention:
it was working properly until some time ago (maybe update of PHP version ??)
same behavior with www/http/https version of the links
standard structure of the links is www.example.com/test/
.htaccess file code
<Files .htaccess>
order allow,deny
deny from all
</Files>
RewriteEngine On
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteRule sample/(.*)/(.*)/$ /sample.php?$1=$2
ErrorDocument 400 /400.php
ErrorDocument 401 /401.php
ErrorDocument 403 /403.php
ErrorDocument 404 /404.php
ErrorDocument 410 /410.php
The difference with your URLs that end in a trailing slash is that they are unconditionally rewritten to the corresponding .php file. The URLs that do not end in a trailing slash are not rewritten - nothing happens.
You are seeing the same basic "File not found" response when you directly request a non-existent .php file, regardless of whether the request is rewritten (by your rules) or not.
The "problem" might be due to the way PHP is implemented on your server. For instance, if all *.php requests are proxied to an alternative backend process then this is going to bypass your .htaccess file on the application server and the "basic" 404 response you are seeing is possibly coming from the proxy, not your application server.
You may be able to resolve this by first checking that the .php exists before rewriting to it (so it doesn't trigger a 404). And if none of your URLs contain a .php extension, you could also force any direct request for .php files to 404 (on your server, before the request is proxied - if that is what's happening).
RewriteEngine On
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteRule sample/(.*)/(.*)/$ /sample.php?$1=$2
The first two rules can also be combined into one. You are missing L flags on all your rules. You need to ensure that MultiViews is disabled, otherwise the last rule will not work.
Also, the regex in the last rule needs to be anchored and made more specific since it is matching too much, eg. /sample/foo/bar/baz/qux will be rewritten to /sample.php?foo/bar/baz=qux, which I assume is not the intention.
Try the following instead:
Options -MultiViews
RewriteEngine On
# Force any direct request for ".php" files to 404
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.php$ - [R=404]
# Rewrite to ".php" file - 1 or 2 path segments
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+(/[^/]+)?)/$ $1.php [L]
# Rewrite "/sample/one/two/"
RewriteRule ^sample/([^/]+)/([^/]+)/$ sample.php?$1=$2 [L]
Reference:
Another recent question that has a very similar issue and was resolved in the same way:
Custom 404 error handler in htaccess not working for non-existent ".php" files
The problem is with ending slash of RewriteRule ^([^/]+)/$ $1.php
If you write RewriteRule ^([^/]+)/?$ $1.php the tailing slash would be optional.
edit
You should also add
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
before RewriteRule statements, because of server loop - when the file exists the statements will break loop by skipping rewriting.

.htaccess remove extension but allow 404 if not existing

I have removed file extensions on .php for my webserver. I just wanted to make it look nicer. This works excellent.
I have the following pages:
sitename.com/portfolio
sitename.com/portfolio/resume/file.html
The htaccess has rules so that when they visit the second link its just converting it to portfolio.php?resume&file=$1. That works awesome.
Okay heres the issue. Because i remove the extensions, if a user were to typ the domain as sitename.com/ portfolio/ with a traing slash, they will get an internal server error. Likewise, if they just type sitename.com/portfolio/r they also get an error since it doesnt exist. I know one way around this is to add an option in htacess for every page but that seems like a bad way of doing it.
Anyways here the current htacess file I am using:
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteRule ^portfolio/resumes/([^/]+).html$ /portfolio.php?resume&file=$1 [L,QSA]
RewriteRule ^portfolio/resumes$ /portfolio.php?resumes [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ /$1.php [L]
ErrorDocument 404 /404.php
If i visit the site on a page that doesnt exist like sitename.com/1 or sitename.com/1.php then I get my 404 page, but if 1.php DID exist then i would see it and IF it did exist, and I typed sitename.com/1/ or sitename.com/1/somethingelse then instead of a 404 (which I expect) then it gives me an internal server error. Is there any way around this? an error in my syntax? Thanks
This is because when you request an uri with a trailing slash eg : /uri/ , your rule rewrites it to /uri/.php instead of /uri.phpwhich is an unknown/unsupported destination. You need to accept the trailing slash as an optional char. Change your rule to :
RewriteRule ^(.*?)/?$ /$1.php [L]

htaccess causes 500 if page doesn't exist

I am currently using this code to remove the .php extension of my files on my apache web server.
Options -Multiviews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.php [L]
two questions:
1: when someone requests a page that doesn't exist, my web server is returning a 500 error instead of a 404. how can I fix this?
2: how can I force a 404 if someone requests the .php extension?
thank you in advance.
The 500 error for non-existent pages is happening because mod_rewrite is going into an infinite loop trying to rewrite your request and terminates eventually.
Rewrite the rules like this to make sure the file with the PHP extension actually exists:
Options -Multiviews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [L]
The RewriteCond %{REQUEST_FILENAME}.php -f line will cause the rewrite to take place only if "file.php" exists.
example.com/about-us.php to go to example.com/about-us.html
RewriteEngine on
RewriteRule ^(.*)\.html$ $1.php
This is not complete answer.
I try to explain how RewriteEngine works, if you don't understand that htaccess feature completely.
Apache server 'receives' some 'not real' url from your browser. Then it reads .htaccess, and by using information from that file it converts that 'not real' url to 'real' url pointing to physical file on server.
Error details are always saved to apache (httpd) error log. You have to read it, and if it not tells you anything - paste it here - we will help.
Forcing 404 error is bad idea in this case. You should fix error, not override it.

Apache request page without PHP extension

Is it possible to request a file with it's .php extension, so for example, instead of going to, http://example.com/about.php the user would only need to type http://example.com/about.
I have tried the following but just get a 404 page,
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.php [L,QSA]
You need to exclude .php from the url because otherwise you can get an infinite loop and it result in an url like this .php.php.php.php. But the idea is good and it works.
How do I remove the '.php' extension from URLs?
Your rules should work if the requested file (after rewriting) exists. For example the page /phpinfo was requested and the file /phpinfo.php exists. But the same rules will create an infinite loop if the file (after rewriting) does not exist, for example:
/phpinfo matches the RewriteRule and both RewriteCond are satisfied, result will be /phpinfo.php
L flag stops current iteration but since filename has changed, another iteration is required
/phpinfo.php matches the RewriteRule and both RewriteCond are satisfied, result will be /phpinfo.php.php
repeat until mod_rewrite gives up
There are few workarounds, the simplest one is to tweak your RewriteCond:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*) $1.php [QSA,L]
If you continuously get 404 error even for simple rewrite rules, chances are that your rewrite rules are not being processed by Apache. A possible reason is that that AllowOverride is set to None in server configuration file (httpd.conf). Change that to AllowOverride FileInfo and restart Apache.

Categories