I have the following in my .htaccess
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^task/(.*)/?$ index.php?mode=task&id=$1 [L]
RewriteRule ^(.*)/?$ index.php?mode=$1 [L]
If the last line is included, no matter what is put in the URL it sets $_GET['mode'] to index.php. Without the last line included, or if I set it to go to index.php?mode=home, for instance, it works fine, but there isn't a catchall.
I don't see what the problem is, but it's probably something simple. If someone else could take a moment to steer me right, that'd b great. Thanks!
When you apply that to ,say, /task/123, this is what happens, (assuming that URI doesn't exist):
passes !-f, /task/123 isn't a file that exists
passes !-d, /task/123 isn't a directory that exists
MATCH against ^task/(.*)/?$ so the URI gets rewritten to index.php?mode=task&id=123
With [L], nothing else happens and the request gets INTERNALLY REDIRECTED to index.php?mode=task&id=123
Internal redirect gets all rules re-applied <--- this is what's screwing you up
no match against ^task/(.*)/?$, do nothing
MATCH against ^(.*)/?$, so the URI gets rewritten to index.php?mode=index.php
initial URL equal rewritten URL: index.php, stop rewriting
What you need to do is add a condition to the 2nd rule:
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^(.*)/?$ index.php?mode=$1 [L]
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'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.
I have the following url:
http://example.com/files/101-info/index.php
My questions is:
Is it possible to remove the 101- in the url?
Is it possible to rewrite the name in the address bar, but keep the file in the current location?
I would like to make the file appear to be at:
http://example.com/files/info/index.php
but actually remain in:
/var/www/htdocs/files/101-info/index.php
Here's what I tried, but I couldn't remove the 101- and the redirect didn't work:
RewriteEngine On
RewriteRule ^([^/]+)/([0-9]+)-([^\/]+)/(.+)\.php$ /$1/$2/$4 [R] // also tried [NC,QSA]
NOTE: Keep in mind if you have other rules in your .htaccess that you have not mentioned in your question and you don't place the below rules at the proper place, it will not work as expected.
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+files/[0-9]+-([^/]+)/([^\s\?]+) [NC]
RewriteRule ^ /files/%1/%2 [R=302,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(files)/([^/]+)/([^/]+)$ /$1/101-$2/$3 [L]
First rule will remove the 101-, the 2nd rule will accept the 101- internally without having to change the folder name or the place your files are.
Change it from [R=302,L] to [R=301,L] once you confirm it is working.
Since you were previously using a redirect, your browser might be cached, so clear you cache and make sure to test the URL with a different browser until the cache of yours is cleared as it doesn't always happen after deleting it.
here is my website
http://www.coolcodez.net/ios/nicucalc
notice when you click on pages on the nav you get urls like
http://www.coolcodez.net/ios/nicucalc/index.php?page=features
I put an .htaccess file in my nicucalc directory. I want the urls to look like this
http://www.coolcodez.net/ios/nicucalc/features
even better would be
http://www.coolcodez.net/nicucalc/features
here is my htaccess file. It's never working properly..
RewriteEngine on
RewriteCond %{QUERY_STRING} ^page=(.*)$
RewriteRule ^index\.php$ /%1/? [R=301,L]
what am i doing wrong. explanation as well please
also note: this folder is located inside of a wordpress installation folder. not sure if that htaccess file would be affecting mine somehow
The rule that you have redirects requests for index.php to /features/ (or whatever the "page" is). This is fine in and of itself but you need something that rewrites it internally back to index.php. Because of that you need 2 rules, one to redirect (matches request) and one to internally rewrite (matches URI):
RewriteEngine On
RewriteBase /ios/nicucalc/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /ios/nicucalc/index\.php\?page=([^&\ ]+)&?([^\ ]*)
RewriteRule ^ /ios/nicucalc/%1?%2 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
The first rule matches against the request, this looks like:
GET /ios/nicucalc/index.php?page=features HTTP/1.1
The "features" is captured and backreferenced in the rule using %1. The second rule first checks if the request points to an existing file or directory. If it doesn't then the URI is captured and then rewritten to index.php and the URI gets passed to the script via the "page" parameter.
I'm trying to build an htaccess file that displays an index file on a blank URI, or a numeric slug (pages), such as: example.com or example.com/12 (the later appending ?page=$1)
However when accessing any non-numeric slug, it should go to a different page. For some reason, I can't get it to ever hit the index file (even when blank or numeric). What am I missing?
Here's what I have:
Options All
RewriteEngine On
RewriteRule ^([0-9]*)/?$ index.php?page=$1 [L]
RewriteRule ^([^/]+)/?$ another_page.php?slug=$1 [L]
Shouldn't a blank URI or numeric URI hit the first rule, with the Last flag, and load index.php? Every request I make is hitting another_page.php
Thanks!
Ah ha, I figured it out shortly after posting this question.
I did require the RewriteCond lines above the final, but the original files had to exist too. I setup this htaccess file before creating the index.php file (I was looking for a 404).
This is what worked:
Options All
RewriteEngine On
RewriteRule ^([0-9]*)/?$ index.php?page=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ another_page.php?slug=$1 [L]
Thanks guys!