I'm trying to rewrite all requests to index.php and then there decide which file to include depending on the value in the $_GET['p'] variable. For example I have a script called update.php in the home directory of my site called leltar, which I would like to be included if the opened page is localhost/leltar/update.
However, the problem is that the rewriting does not work because WAMP runs the script even though the .php extension is not in the link. The output is just the one from the script, nothing is shown from index.php. How can I stop WAMP from running the script with similar name? I suppose, there is something wrong with my .htaccess code as well because if I open pages other than localhost/leltar/update, the value of $_GET['p'] is the string "index.php" all the time.
.htaccess file:
RewriteEngine On
RewriteRule ^(.*)$ index.php?p=$1
index.php:
// ...
switch ($_GET['p']) {
case 'update':
require_once('update.php');
break;
default:
// something else
break;
}
// ...
The content of update.php is not relevant.
EDIT:
The main problem is that by default or even when I use the RewriteCond %{REQUEST_FILENAME} !-f rewrite condition if there is a file with the same name as the user-friendly end of the link, WAMP somehow overrides my rewrite rules. If I put a picture named pic.jpg into the www folder and open localhost/pic.jpg, the image shows up, obviously. However, if I leave out the extension visiting the page localhost/pic, I get the same output as well (instead of getting a 404 Not Found error because of the non-exisiting folder, I suppose).
EDIT 2:
On a real server there isn't any problem. If I leave out the extension a 404 error is thrown, so it's definitely a WAMP-specific thing.
Rules in .htaccess files effectively loop until the URL does not change (because the processing is restarted each time, which means the rules are also processed again) so of course your rule loops until p is equal to itself.
You don't actually need p, you can just check $_SERVER['REQUEST_URI'] in your PHP script and that will tell you the original requested URI (not the same as REQUEST_URI below, which does change with each rewrite).
So just use this:
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^ index.php [L]
But... you probably want files that exist to be served, such as images, scripts etc. so the usual thing is to do this and check if the file exists:
RewriteCond %{REQUEST_URI} !=/index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Although it's more efficient to do this and list the directories with files in them that you want to be served:
RewriteCond %{REQUEST_URI} !=/index.php
RewriteCond %{REQUEST_URI} !^/(?:images|css|scripts)/
RewriteRule ^ index.php [L]
Just change the list to the names of the directories that have your static files in.
Update
From the comments, it seems you have another rewrite that is adding .php to URLs, so they can work without it. In order to not rewrite them to index.php, I suggest putting the rewrite before this one. Otherwise, you can check if the URL exists with .php on the end of it like this. Perhaps combining it with the folder check rather than having two file-system checks.
RewriteCond %{REQUEST_URI} !=/index.php
RewriteCond %{REQUEST_FILENAME}.php !-f
RewriteCond %{REQUEST_URI} !^/(?:images|css|scripts)/
RewriteRule ^ index.php [L]
You can add specific file exceptions to the third rule like this:
RewriteCond %{REQUEST_URI} !=/index.php
RewriteCond %{REQUEST_URI} !^/(?:images|css|scripts)/
RewriteCond %{REQUEST_URI} !=/some/url.php
RewriteCond %{REQUEST_URI} !=/some_other_url.php
RewriteRule ^ index.php [L]
Indeed, as #SuperDuperApps assumed, the problem was that WAMP has MultiViews enabled by default. Adding Options -MultiViews to my .htaccess file solved all my problems, my initial code mentioned in the question works fine now.
Related
I would like to make the URLs of my Store URL-friendly.
Current URL Structure
https://my-domain.com/store/store.php?page=packages&id=1
Desired URL Structure
https://my-domain.com/store/packages/1
And also for direct access to the PHP files such as:
https://my-domain.com/store/profile.php to https://my-domain.com/store/profile
How would I need to go after this? I really appreciate any help you can provide.
Also might be note worthy that in the base directory a WordPress site is running with its own .htaccess file.
I already tried it with this
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^store/store/page/(.*)/id/(.*) /store/store.php?page=$1&id=$2
RewriteRule ^store/store/page/(.*)/id/(.*)/ /store/store.php?page=$1&id=$2
But that didn't work
This code will work.
RewriteEngine will remove .php from all PHP Files
RewriteRule will rewrite url like page/id
For Removing .php extension
RewriteEngine On
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]
For page/id
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9]+)/([a-zA-Z0-9]+)? store.php?page=$1&id=$2 [L]
</IfModule>
You can use this for the first part:
RewriteRule ^store/((?!store)[^/]+)/([^/]+)$ /store/store.php?page=$1&id=$2 [L]
Although nothing is wrong with anyone else's answers, the more modern way to do this (including WordPress, Symfony and Laravel) is to send non-existent URLs to a single router script. By doing this, you only have to mess with an htaccess file once to set things up, and never touch it again if you add more "sub-folders", you can do all of that in just PHP. This is also more portable which means you can bring it to other server platforms such as Nginx with little changes, and don't need to deal with RegEx.
The htaccess is fairly straightforward. Route all requests that start with /store/ and don't exist as a file (such as images, JS and CSS) or directory to a single new file called router.php in your /store/ folder. This is an internal redirect, which means it isn't a 301 or 302.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^store/ /store/router.php [L]
Then in your new router.php file you can parse $_SERVER['REQUEST_URI'] to determine the URL that was actually requested, and you can even rebuild the global $_GET variable:
// Parse the originally requested URL into parts
$requestUrlParts = parse_url($_SERVER['REQUEST_URI']);
// Parse the query string into parts, erase the old global _GET array
parse_str($requestUrlParts['query'], $_GET);
// Handle
switch($requestUrlParts['path']){
case '/store/store.php';
include '/store/store.php';
exit;
// Custom 404 logic here
default:
http_response_code(404);
echo 'The page you are looking for cannot be found';
exit;
}
I'd also recommend putting the htaccess rule into the site root's htaccess folder, above WordPress's. There's nothing wrong with creating multiple files, this just keeps things in a central place and makes it easier (IMHO) to debug.
I'm working on a website that has been built sloppily.
The website is filled with regular links that are translated into the corresponding .php pages by the .htaccess page.
This is it:
RewriteEngine on
RewriteRule ^koral/(.*)/$ page.php?name=$1
RewriteRule ^koral/(.*)$ page.php?name=$1
RewriteRule ^(.*).html/(.*)/(.*)/(.*)$ cat.php?cat=$1&page=$2&order=$3&dir=$4
RewriteRule ^(.*).html$ cat.php?cat=$1
RewriteRule ^(.*)/(.*).html$ product.php?cat=$1&product=$2
<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>
First of all, I would love some help regarding whether or not this page has everything it should. I've never messed with it before.
Secondly and my main issue, if, for example, I would write the address www.thewebsite.com/foobar.html, it would be translated into www.thewebsite.com/cat.php?cat=foobar by the .htaccess page, and it would give a database error (and reveal information about the database).
I've put a check into cat.php which checks if the category exists, but I can't redirect the user to the 404 error page. There's a page called 404.shtml in the website, but redirecting the user to it causes the .htaccess to just change it again to cat.php?cat=404.
Is the way they used the .htaccess page normal? Should I change this system?
And how are users sent to error pages? From what I understood the server should be doing it on its own?
I would love some clarification... There is some much about this subject I don't understand.
Update:
This is my new .htaccess page
RewriteEngine on
RewriteRule ^error.php?err=(.*)$ Error$1.html
# Only apply this rule if we're not requesting a file...
RewriteCond %{REQUEST_FILENAME} !-f [NC]
# ...and if we're not requesting a directory.
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteRule ^koral/(.*)/$ page.php?name=$1
RewriteRule ^koral/(.*)$ page.php?name=$1
RewriteRule ^(.*).html/(.*)/(.*)/(.*)$ cat.php?cat=$1&page=$2&order=$3&dir=$4
RewriteRule ^(.*).html$ cat.php?cat=$1
RewriteRule ^(.*)/(.*).html$ product.php?cat=$1&product=$2
<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>
Because the redirecting is in the code and the user cannot see it, I allowed myself to write the link in a non-clean way. I tried turning it into a clean URL but the following does not do anything:
RewriteRule ^error.php?err=(.*)$ Error$1.html
Can someone please help me understand why? I thought since error.php is a real page, I should put it before the conditional but it didn't work. BTW, I saw in an article about .htaccess that the page should start with Options +FollowSymLinks. It seems to me that everyone sort of has their own way of writing it. Is there a guide or something like that, which I can be sure is authentic and covers all the bases there is about .htaccess?
Thank you so much!!
Using rewrite rules to work around links to .html pages that don't exist is unusual in my experience, but it's really just a different take on "pretty" URLs, e.g. www.thewebsite.com/foobar/ gets routed to cat.php?cat=foobar on the backend.
Your 404 issue is different. You need to be able to display error pages.
One option here is to rewrite requests as long as they don't request an existing file. This is very common for serving up static content like images, CSS files, and the like. To do this, you can use the -d and -f options to RewriteCond, which apply when requesting a directory and file respectively:
RewriteEngine On
# Only apply this rule if we're not requesting a file...
RewriteCond %{REQUEST_FILENAME} !-f [NC]
# ...and if we're not requesting a directory.
RewriteCond %{REQUEST_FILENAME} !-d [NC]
RewriteRule ^([^.]+)\.html$ cat.php?cat=$1 [L,QSA]
Now, requests to 404.shtml should go through, because you're requesting an existing file on the filesystem.
Note that the RewriteConds only apply to the single RewriteRule that immediately follows. For additional RewriteRules, also include additional RewriteConds.
Your regex is wrong anywhere. Literal dot needs to be escaped using otherwise it will match any character. Also it is better to use L and QSA flags to end each rule properly.
RewriteEngine on
RewriteBase /
RewriteRule ^koral/([^/]+)/?$ page.php?name=$1 [L,QSA]
RewriteRule ^([^.]+)\.html/([^/]+)/([^/]+)/([^/]*)/?$ cat.php?cat=$1&page=$2&order=$3&dir=$4 [L,QSA]
RewriteRule ^([^.]+)\.html$ cat.php?cat=$1 [L,QSA]
RewriteRule ^([^/]+)/([^.]+)\.html$ product.php?cat=$1&product=$2 [L,QSA]
I have a directory site and its sub-folder and files in it.
It also contain a .htacess and below is the code
RewriteRule ^([A-Za-z0-9-]+)/?$ index.php?cc=$1
so my below url will is effective and working good.
http://localhost/site/sweetinc
And below code in index.php below
<?php
if (isset($_GET['cc']) and !empty($_GET['cc'])) {
echo $_GET['cc'];
} else {
die("Sorry wrong code");
}
?>
And this is working good.
Now, i want to access or display all files as normally
http://localhost/site/sweetinc/home.php
http://localhost/site/sweetinc/test.php
home.php and test.php are located in site directory. And if it redirects to other sub-folders then it should
be visible like
http://localhost/site/sweetinc/sub-folder1/test3.php
Is this possible, as I am working seperating a group using seperate directory using .htaccess and considering all files in site directory as base files
The trick here (if I understand your question correctly) is that you don't want the rewrite rule to be in effect when you're trying to reach a file that actually exists, right?
In that case, just before your RewriteRule, add these lines:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
That way, the rewriterule only takes effect when the url (/site/sweetinc for example) does not really exist on the server. If it does (/site/sweetinc/home.php) the rewriterule is skipped and the file is shown.
(-f checks if the filename exists, -d checks if the directory exists, so /home/sweetinc/somedir/ should work too)
Update based on updated question
You need two separate rules for this. First of all, if the /sweetinc/ directory in the url is used, refer them to the /site/ folder:
RewriteRule ^sweetinc/(.*)$ /$1 [L]
Then, if the file does not actually exist, let the index.php handle it:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?cc=$1 [L]
Some examples:
I have the following files in my files subdomain:
/index.php (which has the same content as yours does, so it reads out ?cc=
/circle3.PNG
/the .htaccess with the above rules
http://files.litso.com/sweetinc/hello shows the index.php that echoes "hello"
http://files.litso.com/sweetinc/circle3.PNG shows the actual file in /
(note, I don't have a /sweetinc/ directory, it's all faked)
Okay...My title is a bit of an exaggeration...
My site is built in PHP, and all the files I'm trying to "require_once" aren't being loaded. The only file I've changed is my .htaccess file. I don't know a thing about .htaccess and what I have is purely from searching the web. What is wrong? Thanks for any help in advance.
RewriteEngine on
<Files 403.shtml>
order allow,deny
allow from all
</Files>
ReWriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
ReWriteRule !index.php index.php [L]
Also, if I comment out the bottom two lines, my site works great.
Well, require_once has nothing to do with .htaccess file: it's a PHP directive, not an Apache one. You have to set correctly the include_path for your files and make sure these directories and files are reachable (i.e., with correct privileges set on them).
If you show the error message you got from failed require, it'd be much more simple to give you a specific advice on how to fix it.
UPDATE If what you need is redirecting all the non-AJAX requests for .php files into index.php, your .htaccess should like this:
RewriteEngine on
RewriteCond %{HTTP:x-requested-with} ^XMLHttpRequest$
RewriteRule . - [L]
RewriteCond %{REQUEST_FILENAME} !-d
ReWriteRule .php$ index.php
This basically means the following: "all AJAX requests - go for what you need, all non-AJAX requests IF you're not going for some directory and are ended with .php - go for index.php instead".
Without checking for .php (or some similar check) you will redirect to index.php all the script loading procedures; and, unless you do it from some external CDN, it's not what would work in your case. )
Try changing the last two lines to this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
If you want your URL's to look something like this (you probably do):
http://yoursite.com/some/path/somewhere
then change the last line to:
RewriteRule ^([^/]*)(.*)$ index.php?first=$1&second=$2
If that's what you want to achieve, ensure that if you're trying to go to:
http://yoursite.com/about
That there isn't actually a folder called about, this line:
RewriteCond %{REQUEST_FILENAME} !-d
Checks to see if a folder with the name "about" exists, if it does, then the page will not redirect, the same goes for files, say you go to:
http://yoursite.com/about.html
If about.html actually exists then the page will not redirect.
Hope that makes sense.
If you need more information, http://jrgns.net/content/redirect_request_to_index seems to be fairly succinct and helpful.
I need to redirect if someone goes to any folder e.g. http://site.com/images/ or http://site.com/images to http://site.com.
Unless he goes to file e.g. http://site.com/images/index.php in this case it does not redirect
now i use
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} (.*)$ [NC]
RewriteRule ^(.*)$ http://%1/ [R=301,L]
but i think its not perfect because e.g. if someone comes on http://www.site.com it does not work.
Keep in mind due to server configuration i need to put .htaccess in every folder.
I believe that what you are looking for is the -f flag:
RewriteCond %{REQUEST_FILENAME} !-f
See http://httpd.apache.org/docs/current/mod/mod_rewrite.html
If you are only looking at stopping someone from getting a list of the files you have in the folder, you may want to consider instead adding:
Options -Indexes
This will tell apache not to display a directory list if no index page is present in the given directory.
See http://httpd.apache.org/docs/2.2/mod/core.html#options
The last thing to note, if you are not familiar with how .htaccess works, apache scans the current folder and any of its parent folders - you should be okay with only adding a single .htaccess file in your web root for http://site.com. This has been covered in another question here.