I currently have a .htaccess file that allows people to enter the URL without the php extension, such that http://domain.com/account redirects to account.php
I would like to be able to have it so that if I enter http://domain.com/account/contactinfo (or http://domain.com/account/settings/groups and so on) it still goes to account.php, but I am not sure how to change what I have to achieve this.
Current .htaccess :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(([A-Za-z0-9\-_\.]+/)*[A-Za-z0-9\-_\.]+)?$ $1.php
Any help appreciated! Obviously if there exists a folder it should follow that path (e.g. if /folder/page.php exists, then http://domain.com/folder/page/create would go to folder/page.php)
Try this is you don't need to pass any URI info into query string (i.e. your app will still look at $_SERVER['REQUEST_URI'])
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([A-Za-z0-9\-_\.]+)(/[A-Za-z0-9\-_\.]*)?$ $1.php&q=$2 [QSA]
# Note the optional '&q=$2' on line above if you want to make removed part of URI available as passed parameter
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ / [L,QSA]
Note that since I removed the condition to check for a valid php file, I added a second conditional rewrite rule to just redirect to site root if the re-written request does not point to a valid PHP file. You could obviously redirect this to a 404 page or whatever else you might want to redirect to. Or you could remove this altogether and let Apache give it's default 404 response.
Related
I am working on a CodeIgniter project and today I found a very strange issue.
When I open the URL that is prefixed with index.php in the first segment it is still working even though I expect the URL to return a 404 Not Found page.
For example, the URL of my website is http://localhost/project and when I open the URL http://localhost/project/jobs it works fine, but when I open http://localhost/project/index.phpjobs it also works.
I don't know what is going on over here!
Please note that the URL doesn't include slash but is still working and that is not a typo.
Please check in your project and let me know if someone have the same problem because I think this problem may also exist in your current project but not noticed.
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^admin(.*)$ admin/index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
RewriteRule ^.well-known/ - [L,NC]
Your first rewrite rule
RewriteRule ^admin(.*)$ admin/index.php?/$1 [L]
will be honored only if the previous two conditions
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
have been met.
Now, the trick lies in these conditions which basically say that the rewrite will be performed only if the requested resource (REQUEST_FILENAME here) does not exist as either a file or a folder.
Since index.php obviously exists the rewrite rule is skipped and the server actually receives the original (non-rewritten) request.
That is the reason why you see the same result for requests that both do and do not contain /index.php/ as prefix.
The same applies for both sets of rewrite, the one you are using for your admin page and the regular one.
I have this code in my htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^(.+)$ index.php/?url=$1 [QSA,L]
And in PHP, I grab the current url request and give it it's controller so if there was http://example.com/index.php?url=about -> this will give me the about controller so it displays the about page (MVC)
Now my question is that how can I remove the index.php?url from every page. For example I want to access the about page then I need it to be -> http://example.com/about
You can see in the htaccess that I am replacing the index.php/?url with whatever I type ($1) But it doesn't seem to work because when I request this url: (example) http://example.com/about I get Object not found! Error 404. And when I have http://example.com I get the controller_home page. However, when i type http://example.com/home it also displays error 404.
If I do this: http://example.com/?url=about or http://example.com/index.php?url=about it works find and gives me the about controller so the ?url isn't getting removed by the htaccess I guess...
Might that be an another error in my php code or what?
Kindly help me as I have been looking over this error about 10 hours and I didn't find why it is behaving like that, my friend has almost the same code and it works perfectly for him.
I am kind of new to php so it might be simple bug...
Thanks in advance for everyone that helps!
If you're using an .htaccess file
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^/?(.+)$ index.php?url=$1 [QSA,L]
If you're editing the main apache config file (httpd.conf or apache2.conf). I know the OP is using .htaccess but just in case other people having this issue see this discussion:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-l
RewriteRule ^/?(.+)$ index.php?url=$1 [QSA,L]
First, presumably you want to test if the requested string does NOT match a directory, NOT match a file, and NOT match a symbolic link - so you need add a "!" before the RewriteCond flags (to negate the condition). Stacked RewriteConds are linked with an implicit AND so checking for directory, file and symbolic link doesn't make sense (a given requested string wouldn't match all of these conditions).
Second, the %{DOCUMENT_ROOT} would be necessary if you're doing this in the main apache config file (ie/httpd.conf or apache2.conf). It's not necessary if you're doing this in an .htaccess file.
Third, when RewriteRule is matching it includes the /. Presumably when you request "website.com/about" you want "about" to be passed to index.php not "/about", so the "/?" will remove the / in first character position from $1. I put the question mark, just because I think it's best practice, since technically you could get an HTTP request that does not begin with a slash (although this would be against standards and every browser includes a slash at the beginning).
Fourth, you shouldn't put a / after the index.php in RewriteRule (so it should be "index.php?url=$1", not "index.php/?url=$1". Query strings are separated from a filename via a "?" not a "/?".
Try this
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^(.*)$ http://%1/$1/ [R=301,L]
RewriteRule ^((.*)+)$ index.php?url=$1 [QSA,L]
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.
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.
So to begin with I have a custom url rewrite that sends a request variable to a php script
Rewrite rule is below:
RewriteRule ^([\w\/-]+)(\?.*)?$ test/index.php?slug=$1 [L,T=application/x-httpd-php]
So if you access something like domain.com/slug-text it sends slug-text to index.php located in folder named test.
What I want is all my urls to look like domain.com/slug-text.html, but slug-test variable should still be sent to index.php file.
And
What I can't figure out is the redirect. I want all the old urls to be redirected from domain.com/slug-text or domain.com/slug-text/ to domain.com/slug-text.html and slug-text sent to index.php file located in test folder.
Searched a lot but could not find the answer for this question anywhere on the Internet.
Thank you all for the help.
UPDATE:
my new code is:
RewriteEngine On
Options +FollowSymlinks
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-l
RewriteRule ^(([\w/\-]+)?[\w-])(?!:\.html)$ http://domain.com/$1\.html [L,R=301]
RewriteRule ^(([\w/\-]+)?[\w-])(/|\.html)?$ test/index.php?slug=$1 [L]
domain.com/slug-text/ does not get redirected to domain.com/slug-text.html
domain.com/slug-text works as intended redirecting to domain.com/slug-text.html
What do i need to change?
This rule:
RewriteRule ^(([\w/\-]+)?[\w-])(/|\.html)?$ test/index.php?slug=$1 [L]
Will trap domain.com/slug-text, domain.com/slug-text/ and domain.com/slug-text.html and send slug-text to /test/index.php inside slug param.
If you really want to redirect using [R=301] from old urls to new then use this:
RewriteRule ^(([\w/-]+)?[\w-])/?(?!:\.html)$ http://domain.com/$1.html [L,R=301]
RewriteRule ^(([\w/-]+)?[\w-])\.html$ test/index.php?slug=$1 [L]
Also note that as using explicit redirect bottom rule is modified to trap url's ending with .html
It is also advisable (if your .htaccess does not already contain this) to filter conditions for existing files and folders not to be trapped by your redirect rules. Simply add these lines before RewriteRule lines:
# existing file
RewriteCond %{SCRIPT_FILENAME} !-f
# existing folder
RewriteCond %{SCRIPT_FILENAME} !-d
And if using symlinks:
# enable symlinks
Options +FollowSymLinks
# existing symlink
RewriteCond %{SCRIPT_FILENAME} !-l
// addition
Your .htaccess file should look like this:
RewriteEngine on
Options +FollowSymLinks
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-l
RewriteRule ^(([\w/-]+)?[\w-])/?(?!:\.html)$ http://domain.com/$1.html [L,R=301]
RewriteRule ^(([\w/-]+)?[\w-])\.html$ test/index.php?slug=$1 [L]
This is supposed to redirect /slug-text to /slug-text.html
RedirectMatch ^/([\w-]+)/?$ http://domein.com/$1.html
This is in the case when slug-text is only letters, digits, – and _.
Rewrite slug-text.html to a php file and pass the slug as a param:
RewriteRule ^([\w-]+)\.html$ test/index.php?slug=$1 [R,L]
If you have both line in your .htaccess the first one will do the redirects from the legacy URLs to the new ones and the second one will process the request.