Mod rewrite rule doesn't work - php

I'm working with mod rewrite, but my code doesn't work. It worked for a time.
I have stripped the code.
.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^/(.*)/$ index.php?test=$1
PHP
<?php
var_dump($_GET['test']);
?>
If I go to the index.php it displays NULL.
I don't understand why it doesn't work anymore. I hope you can help me.
P.s. I have tested whether the .htaccess file is loaded by making a login form with .htaccess.

You need to get rid of the first slash:
RewriteRule ^(.*)/$ index.php?test=$1
And even then your rule will only apply when you enter a url that ends with a forward slash, so for example:
/index.php/
If you want it to work with any url, you need to remove the last slash as well:
RewriteRule ^(.*)$ index.php?test=$1
Edit: To avoid rewriting of existing files and directories you need add some conditions:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?test=$1

You need to remove the first slash in your rule
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)/$ index.php?test=$1

Related

htaccess adding [NC,F] to GET parameter

I'm working on an MVC project and I have the following .htaccess file:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [L]
RewriteRule !^(public/|index\.php) [NC,F]
It works OK. I only want the public/ folder and the index.php file to be accessible to the public. All other paths should be inserted into the path GET parameter. For example, mysite.com/controller/method should point to mysite.com/index.php?path=controller/method.
Now, there is a problem. When visiting the URL directly (without including index.php, it is adding [NC,F] to the GET path parameter. It's like visiting mysite.com is pointing to mysite.com/index.php?path=[NC,F].
Why is this happening and how do I fix it?
EDIT
I moved index.php into the public/ folder. Here is my .htaccess file now:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule ^(/)?$ public/index.php [L]
RewriteRule !^(public/) [NC,F]
It seems to work OK. Are there any other improvements I could make on this?
You don't have a redirect location on the last rule, so it's taking the flags as the redirect location. Just a dash will be fine since it's a forbidden response. Change the last line to:
RewriteRule !^(public/|index\.php$) - [NC,F]
Also adding the dollar sign after index.php just to be clear.
Edit:
I would suggest updating your new rule set to the following (actually I suggest a complete re-think below, but this is an update on what you have):
RewriteEngine On
RewriteRule ^$ public/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule !^(public/) - [NC,F]
The (/)? wasn't needed in your homepage rule, as the opening forward slash is not included in .htaccess matches anyway.
I moved your rule for the homepage to the top or it will never be used due to being matched by the previous rule (so the path param is not there when empty, which is presumably what you intended).
I stopped anything in /public/ from being passed to your index.php script, since the way you had it, anything in public that didn't exist would have been passed to your index script, which does not seem to be what you intend.
I added RewriteCond %{REQUEST_URI} !=/public/index.php so the rule couldn't be executed on itself and create a loop if rule processing is run through more than once, which it can be, but then took it back out because the above match on /public/ covers that anyway.
A Re-Think
All that said, I don't think it really makes sense to check if files don't exist and then just send forbidden responses to the ones that do, yet send everything else to your index script. Why not just send everything to your index script? That seems to be what you want really. I would suggest you simplify to this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
Dropping the homepage rule since no need to worry about an empty path parameter being passed to your index script. Changing the logic to be "Leave anything in /public/ alone. For anything else, pass it through to the index.php script." so files tests not needed since the script handles it all, and no forbidden response needed because there is nothing left to match, it's all covered by the rules. You can always return forbidden to anything you don't want to process in your script, which you would have needed to do anyway for existing file URLs in your previous setup.
One Last Re-Think
And finally, if I might suggest, it would be cleaner to have your index.php file in the root of the website, so you can make /public/ work with its own index file later if you like, so finally I would move it back to the root and change the rules to this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^(.*)$ index.php?path=$1 [L]
And if you like all that, an up-vote to go with already accepting the answer would be much appreciated. :)
Adding RewriteRule ^(/)?$ public/index.php [L] seems to have resolved the issue. I'm not sure if this is the best approach, but here is my .htaccess file now:
Options -Indexes
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/index.php?path=$1 [L]
RewriteRule ^(/)?$ public/index.php [L]
RewriteRule !^(public/) [NC,F]
I moved index.php into the public folder to make things clearer.

htaccess rewrite subdirectoy to file

I have a problem with rewriting urls to my files. What I am trying to do is making my little shop system a bit more SEO friendly. My problem is that it sometimes works and sometimes it doesn't. I have no idea what I should do or what I am doing wrong.
My UPDATED .htaccess file:
ErrorDocument 404 /shop/404.html
RewriteEngine On
RewriteBase /shop/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^produkte/?(.*)$ products.php$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^produkt/?(.*)$ product.php?url=$1 [L]
RewriteRule ^(.*)/(css|js|img|fonts)/(.*)?$ /shop/$2/$3 [L,QSA,R=301]
For example the /shop/products link is not working but /shop/products/ is.
And for some reason if I want to open the link /shop/products?cat=besteck its redirecting me to: localhost/D:/xampp/htdocs/shop/products.php?cat=besteck but If I capitalize the b it's working fine..
I have no Idea what to do, please help me! (And dont just give a working code snippet explain why mine fails and yours works)
EDIT:
Just to clear things up I want /products, /products/ and /products?some_get_query to redirect to my products.php file. /product/some_seo_url should be redirected to product.php?url=some_seo_url. I tried adding a question mark after the forward slash in my RewriteRule and I also tried putting the ^products rule above the ^product rule. Nothing worked yet.
EDIT 2:
I updated my .htaccess code above and now nearly everything works. The only thing that still doesn't work is when I open /shop/products/?cat=fish or /shop/product/some_product, my resources aren't loading!
ErrorDocument 404 /shop/404.html
RewriteEngine On
RewriteBase /shop/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^products/?(.*)$ products.php?$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^product/?(.*)$ product.php?url=$1 [L]
RewriteRule ^(.*)/(css|js|img|fonts)/(.*)?$ /shop/$2/$3 [L,QSA,R=301]
First off your product rule also matches products so a rewrite like:
products/cat/fish becomes product.php?url=s/cat/fish
Which is not what you want, the easiest way to avoid that is to reverse the order so that the products rewrite comes before the product one but I've also added the Last flag ([L]) to be on the safe side; besides, once it's got the match you want it's better for it to stop looking.
To prevent recursive rewrite loops you need to specify that the rewrite only occurs when the redirect is not an existing file or directory (otherwise your product rewrite matches product.php and it loops - forever). That's what those RewriteCond lines signify.
Other than that it seems OK.

.htaccess mod_rewrite check if querystring var is avail

Basically I want to rewrite my urls so that it is website.com/folder/ sometimes though I need it to rewrite also website.com/folder/page/
Currently I have it working with just the website.com/folder/ but can not get it to check if there is a page, if I create just another rule under the folder one it reads that one, and gives me an empty page var, which is breaking my php. I struggle with .htaccess and any help would be appreciated.
Here is what I have that works with just the folder but I can not include a page.
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|docs)/
RewriteRule ^([^/]*)/$ /?folder=$1 [QSA]
Here is what I tried to get it to work with either just a folder, or a folder and page
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/$ /?folder=$1 [QSA]
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/([^/]*)/$ /?folder=$1&page=$2 [L,QSA]
Please Help!
Accordingly to the RewriteRule docs you should reverse the rules order in your rules set. Because in your configuration both rules have the same RewriteCond, the most specific rule (folder + page) should be atop and the most general rule should be the last one. If not when the first rule is matched the URL is rewritten and the second rule never matches. Also, probably you want to remove the trailing forward slash in the pattern of your folder + page rule (assuming that the second group in the pattern matches a page not a folder). So I think the whole thing should read:
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/([^/]*)$ /?folder=$1&page=$2 [L,QSA]
RewriteCond %{REQUEST_URI} !^/?(css|js|images|html|doc)/
RewriteRule ^([^/]*)/$ /?folder=$1 [L, QSA]

Issue with mod_rewrite when accessing directory

My code:
RewriteEngine on
RewriteBase /
RewriteRule ^article/([a-z]+)/?$ index.php?page=article&name=$1 [L]
RewriteRule ^([a-z]+)/?$ index.php?page=$1 [L]
I am using WAMP and had setup a Virtual Host.
In my index.php, there is code to get page passed and checks if it exists(in database). If not, display an error message. It works fine.
Eg: http://mysite/contactus/
But it will not work if I use a a directory name as page_name in the URL. Eg: http://mysite/images/. This will display page not found error (ie. checks database and no page found, so display "not found"). But it will not display images,css(linked file) in the page. Also, it shows http://mysite/images/?page=images in addressbar.
Like that, if I goto js folder which is used to store javascript files, above problem occurs. So, problem is caused if any subdirectory's name is passed as pagename.
How to solve this ?
When http://mysite/images/ is supplied, mod_rewrite is redirecting to http://mysite/images/index.php?page=images instead of http://mysite/index.php?page=images
Edit
Please tell me how to block hotlinking of files and directory, and redirect back to index page or send some browser header error ?
I tried this:
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*) http://%{HTTP_HOST} [R,L]
RewriteRule ^article/([a-z]+)/?$ /index.php?page=article&name=$1 [L]
RewriteRule ^([a-z]+)/?$ /index.php?page=$1 [L]
Edit
New code(semi-working):
RewriteEngine on
RewriteBase /
# remove trailing slash ONLY if it is not an existing folder
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1/ [R,L]
RewriteRule ^article/([a-z]+)/?$ http://%{HTTP_HOST}/index.php?page=article&name=$1 [L]
RewriteRule ^([a-z]+)/?$ http://%{HTTP_HOST}/index.php?page=$1 [L]
This code will clear the problem with not displaying pics and css when a directory name is mentioned. But whatever pagename i specify eg:http://mysite/contactus, it will goto URL: http://mysite/index.php?page=contactus. Even if I use a directory name eg: http://mysite/js, it will goto: http://mysite/index.php?page=js
I am very confused.
RewriteEngine on
RewriteBase /
RewriteRule ^article/([a-z]+)/?$ index.php?page=article&name=$1 [L]
RewriteRule ^([a-z]+)/*$ /index.php?page=$1 [L]
you have to put the slash in front.
Edit: changed the ? to *
My understanding is that your script is for documents only, not images or other resources.
Then you should ignore them right away. Try adding this line right after RewriteBase like this :
RewriteEngine on
RewriteBase /rewrite/
RewriteRule ^/(images|js)/(.*)$ - [L]
RewriteRule ^article/([a-z]+)/?$ index.php?page=article&name=$1 [L]
RewriteRule ^([a-z]+)/?$ index.php?page=$1 [L]
Then these subdirectories would be served right away, thus bypassing the next RewriteRule set.
For the problem with the directories I usually force a slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+[^/])$ $1/ [R]

.htaccess rewriting url to page or directory

For my site I have a RewriteRule that points the URL http://www.mysite.com/work to a work.php file. I also have a directory called "work" that has files in it, like project1.php, project2.php, etc...
What rules would I have to write so that the URL http://www.mysite.com/work knows to go to the work.php file, but the URL http://www.mysite.com/work/project1 knows I mean to go inside the directory "work" and display the project1.php file?
EDIT: Should point out, this is what I'm currently working with:
RewriteEngine On
RewriteBase /beta/
RewriteRule ^([a-z]+)$ $1.php [L]
Any additional tips to improve this security-wise? (Stopping directory jumping, etc...)
Try this:
RewriteEngin On
RewriteBase /
RewriteRule ^work$ /work.php [QSA,L]
That will ensure that http://www.mysite.com/work (no trailing slash) will go to your work.php file.
If you also want http://www.mysite.com/work/ (with trailing slash) to go work.php, add this line just above the last RewriteRule.
RewriteRule ^work/$ /work [R=301,QSA,L]
That will redirect it to the URL with no trailing slash thus, displaying the work.php file.
UPDATE: Since you already have a RewriteBase directive, just put the RewriteRule line(s) right after your RewriteBase but before your RewriteRule as the rule you're using a catch-all and will match everything.
This is the answer to your question. It works for me.
RewriteEngine On
RewriteBase /
RewriteRule ^([a-z]+)$ $1.php [L]
Simply remove beta/
Try this rule:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .* $0.php [L]

Categories