.htaccess file - Wildcard Subdomains Redirect - php

I have got a lot of subdomains configured using wildcard e.g.
subdomain1.domain.com
subdomain2.domain.com
subdomain3.domain.com
(...)
subdomain89.domain.com
etc etc.
They are point to /public_html/. Inside the public_html I have created
/public_html/subdomain1
/public_html/subdomain2
/public_html/subdomain3
(..)
/public_html/subdomain89
sub-folders.
I would like to redirect all request from subdomains (any) to index.php files within the respective sub-folders e.g.:
http://subdomain1.domain.com/
http://subdomain1.domain.com/about_us.php
http://subdomain1.domain.com/contact.php
redirects to /public_html/subdomain1/index.php.
http://subdomain2.domain.com/
http://subdomain2.domain.com/about_us.php
http://subdomain2.domain.com/contact.php
redirects to /public_html/subdomain2/index.php etc etc.
This is my .htaccess:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.domain\.com$ [NC]
RewriteRule !^([a-z0-9-]+)($|/) /%2%{REQUEST_URI}/index.php [PT,L]
When I access subdomain1.domain.com i see the index.php file from /public_html/subdomain1 but when I access subdomain1.domain.com/about_us.php i got 404. Any ideas?
Thanks

I have figured it out. This is the working code:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.domain\.com$ [NC]
RewriteRule !^([a-z0-9-]+)($|/) /%2%{REQUEST_URI}/ [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
:-)

First make sure that your .htaccess file is in your document root (the same place as index.php) or it'll only affect the sub-folder it's in (and any sub-folders within that - recursively).
Next make a slight change to your rule so it looks something like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
At the moment you're just matching on . which is one instance of any character, you need at least .* to match any number of instances of any character.
The $_GET['path'] variable will contain the fake directory structure, so /mvc/module/test for instance, which you can then use in index.php to determine the Controller and actions you want to perform.
If you want the whole shebang installed in a sub-directory, such as /mvc/ or /framework/ the least complicated way to do it is to change the rewrite rule slightly to take that into account.
RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]
And ensure that your index.php is in that folder whilst the .htaccess file is in the document root.
Alternative to $_GET['path'] (updated Feb '18 and Jan '19)
It's not actually necessary (nor even common now) to set the path as a $_GET variable, many frameworks will rely on $_SERVER['REQUEST_URI'] to retrieve the same information - normally to determine which Controller to use - but the principle is exactly the same.
This does simplify the RewriteRule slightly as you don't need to create the path parameter (which means the OP's original RewriteRule will now work):
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]
However, the rule about installing in a sub-directory still applies, e.g.
RewriteRule ^.*$ /mvc/index.php [L,QSA]

Related

How to redirect all requests within a subfolder

I have a website called mydumbwebsite.com/. In my root folder, I have various folders, one of them being "stuff". This folder is directly accessible with mydumbwebsite.com/stuff/. I want to create an .htaccess file that redirects everything that goes into this subfolder and only this subfolder, so these urls:
mydumbwebsite.com/stuff/test
mydumbwebsite.com/stuff/test/
mydumbwebsite.com/stuff/test.php
mydumbwebsite.com/stuff/test.php?test=yes
mydumbwebsite.com/stuff/test2.php (doesn't exist)
mydumbwebsite.com/stuff/test2.php?test=yes (doesn't exist)
mydumbwebsite.com/stuff/test/moar
mydumbwebsite.com/stuff/test/moar/tests.php
... should all redirect to the index.php file of the folder "stuff", even if the file/folder they point to exists.
Some additional context: despite my made up example, I encountered this problem on localhost. I have many different projects and I don't want the .htaccess of one project interfere with the other projects. I tried this, but it keeps redirecting me to the xampp homepage:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php [QSA,L]
I tried changing it to this, but that couldn't cover all instances, such as nr. 2, 3 and 4:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /stuff/index.php [QSA,L]
You need to remove the conditions !-d and !-f, which say "Don't apply the rule on existing files and directories". You also need to remove RewriteBase /.
RewriteEngine On
RewriteRule ^(.+)$ index.php [QSA,L]
The file should be located under /suff/.htaccess.
The following rules do also work for me:
RewriteEngine On
RewriteRule ^ index.php [L]
and
RewriteEngine On
RewriteRule ^ index.php [END]
Regarding your comment:
Usually I would create a public folder and put anything that should be accessed directly (public/css/, public/js, public/img etc.) in it. And whitelist it as following:
RewriteEngine On
RewriteRule ^public/ - [END] # allow direct access on public folder
RewriteRule ^ index.php [END] # anything else will be directed to index.php
You can of course whitelist multiple directories the same way:
RewriteEngine On
RewriteRule ^css/ - [END]
RewriteRule ^img/ - [END]
RewriteRule ^js/ - [END]
RewriteRule ^ index.php [END]
Or something like you suggested in the comment:
RewriteRule ^(scripts|styles|morefoldernames)($|/) - [L]
It is late, so my brain could be muddled about this, but surely you simply want everything in stuff to be redirected to index.php, no if's or buts.
Then the below should work, provided it has "/stuff/" in the URL. I'm guessing that you aren't bothered about query strings etc either, if so, then you'll need to modify the index.php below to index.php?$1 and the flags to [QSA, NC, L].
RewriteEngine On
RewriteRule ^/stuff/?$ /stuff/index.php [NC,L]
Check that your root .htaccess file has the line "RewriteOptions InheritDown" somewhere in it, that way the .htaccess file for each subfolder should be covered.
Try this out.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/stuff/(.+)$ /stuff/index.php [L]

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.

File names to indicate pseudo directories using mod_rewrite

Is it possible to use file name strings as an indicator for mod_rewrite to return pseudo directories?
I'll elaborate:
In my root directory (public_html) I have a directory named "pages" which contains the following files:
example.php
example--abc.php
instance.php
instance--2.php
Is it possible, using mod_rewrite to acheieve the following:
example.com/example/ retrieves the file of /pages/example.php
example.com/example/abc/ retrieves the file of /pages/example--abc.php
example.com/instance/ retrieves the file of /pages/instance.php
example.com/instance/2/ retrieves the file of /pages/instance--2.php
and so on...?
Thus far I have used the following with success to point /example to /pages/example.php
RewriteCond %{REQUEST_URI} !pages/
RewriteRule ^(.*)$ pages/$1.php [L,QSA]
However, it's beyond my current grasp to get the pseudo directories working defined by a double hyphen in the target's filename (--).
I've searched long and hard for a solution to no avail.
Also, the above code doesn't allow for a trailing slash (and it should, in an ideal world)
Any help much appreciated.
Thanks,
JC
Based just on description, you can try this:
UPDATED
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/pages
RewriteRule ^([^/]+)/([^/]+)/?$ pages/$1--$2.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/pages
RewriteRule ^([^/]+)/?$ pages/$1.php [L]

Running Yii from subdir. Remove subdir with .htacces, while .css,.js and existing files and dirs still are available

I've been searching for 4 hours by now and I still can't get this to work.
I have the following directories in my webroot:
- application
- assets
- css
- config
- protected
- .htaccess
- ...
- .htaccess
- framework
- [Yii framework inside]
- .htaccess
The .htaccess in my webroot should redirect/'rewrite' all requests for whatever xxx/xxx to http://www.example.com/application/ as long as the requested file or directory does not exist.
This way requests for .css, .js and other files can still work.
In my config I made sure Yii expects SEO friendly URL's and I don't tend to use the index.php. So it now looks like this:
'urlManager'=>array(
'urlFormat'=>'path',
'showScriptName'=>false,
'rules'=>array(
'' => 'site/index',
'<controller:\w+>/<id:\d+>'=>'<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
),
'request' => array(
'baseUrl' => 'http://www.example.com',
),
The 'request' was added later on because Yii was generating links as example.com/application/site/login. With the request Yii generates example.com/site/login instead.
In the .htaccess in my webroot I tried about everything.
First I was able to 'remove' the subdir from the URL. The index page was shown.
I tried to add a rule so all none existing directories would be redirected to the same url.
My first rule broke, and 'application' was in the URL again, but no css styles were loaded.
At this moment I got the index page with css, but now everything brings me to the index page.
my .htaccess looks like this:
RewriteEngine on
RewriteCond $1 !^application/
# if a directory or a file exists, use it directly
RewriteCond %{DOCUMENT_ROOT}/application/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/application/$1 -d
RewriteRule ^(.*)$ application/$1 [L]
# otherwise forward it to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^.*$ application/index.php
Mod_rewrite is enabled (I know because some things worked before). I looked at examples from the Yii docs.
I tried solutions from other questions on Stack Overflow like this one and many many others.
Still no luck.
Could someone please help me out?
edit:
With the .htaccess above a request to example.com ends at example.com/application .. I however would like to make the 'application' 'invisible' again (worked before, don't know why it broke)
I did change my .htaccess as follows:
RewriteEngine on
RewriteCond $1 !^application/
# if a directory or a file exists, use it directly
RewriteCond %{DOCUMENT_ROOT}/application/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/application/$1 -d
RewriteRule ^(.*)$ application/$1 [L]
# otherwise forward it to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ /application/
RewriteCond %{HTTP_HOST} ^(www.)?brainfeeder.be$
RewriteRule ^$ application/$1 [L,QSA]
But still a url like www.brainfeeder.be/site/login brings me to the default controller/action which is the site/index.
I guess my conditions or rules are not exactly correct yet.
Please see my small test application I set up to tackle this issue.
What happens: brainfeeder.be get rewritten to brainfeeder.be/application/ My Yii app is in there so it runs the 'bootstrap' index.php file and gets to the default controller/action, in this case site/index.
Now when you click the 'login' button it should show you a login form. But it stays at the site/index view.
Ok, once again I updated my .htaccess a couple of times. Now I have the following situation:
www.example.com AND example.com are rewritten to www.example.com/application AND example.com/application.
(www.)?example.com/existingfolder just shows content of 'existingfolder'.
(www.)?example.com/var1/var2/../varn get redirected to (www.)?example.com/application/var1/var2/.../varn
Now the only thing I would like to happen is that the latter gets rewritten instead of redirected. So visitors don't know they are in the directory 'application'.
So (www.)?example.com/var1/var2/.../varn would bring the visitor directly to the correct page.
The contents of my .htaccess at the moment:
Options +FollowSymLinks
#IndexIgnore */*
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www.)?brainfeeder.be$
RewriteRule ^$ /application/ [L]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]
# The directory or file does not exist
RewriteCond %{REQUEST_FILENAME} !-s [OR]
RewriteCond %{REQUEST_FILENAME} !-l [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /application/$1 [L,R]
The thing is, when losing the R flag in the last RewriteRule will bring me to the index.php file inside 'application' but it shows the home page instead of a login form when for example I go to example.com/site/login.
Which, I guess, the script does not see the vars. (if it did site/error would trigger) So it handles this as a request to example.com/application and not as example.com/application/var1/var2
I hope I did explain the problem better this time.
Thanks for the great help 'till now.
Try to check these configuration directives if you just want to rewrite all the unexisting /$var1/$var2 to /application/:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ /application/
Now, if you want those unexisting files to redirect, rather than to rewrite them? Then just add a [R] flag at the end of the RewriteRule directive, just don't forget a single " " space before the flag.
Now, if you want to redirect /application to / and then rewrite /index.php to /application and to rewrite also the unexisting /$var1/$var2 to /application/$var1/$var2 then it's quite hard (and need some exact details) but you could still try these configuration directives:
RewriteEngine on
# rewrite index.php
RewriteRule ^index.php$ /application
# rewrite unexisting files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ /application/$1/$2
# try to remove this if it causes redirection loop
RewriteRule ^application/?$ / [R]
You can also try to use DirectoryIndex application/index.php at the very top of those directives to change the index of your site and remove the line RewriteRule ^index.php$ /application if it causes an error.
Actually, I can't understand your question.. You said:
The .htaccess in my webroot should redirect/'rewrite' all requests for
whatever xxx/xxx to http://www.example.com/application/ as long as the
requested file or directory does not exist. This way requests for
.css, .js and other files can still work.
And now, you said to your comment:
So any link to brainfeeder.be/application/$var1/$var2 should be shown
as brainfeeder.be/$var1/$var2
If you would also like to redirect existing /application/$var1/$var2 to /$var1/$var2 then please try to add these directives, and if it causes an error to your system, just remove it:
# the condition is important as mentioned above
RewriteCond %{REQUEST_URI} !\.css$
RewriteRule ^application/([^/]+)/([^/]+)/?$ /$1/$2 [R]
You can add another condition (as many as you like) at the top of the RewriteRule, just use your thinking if you're a programmer. You could add another condition like RewriteCond %{REQUEST_URI} !\.jpg$ if you doesn't want to redirect the file with an extension like .jpg or else that you want such:
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteCond %{REQUEST_URI} !\.png$
RewriteRule ^application/([^/]+)/([^/]+)/?$ /$1/$2 [R]
Please try to change the source of your .htaccess file with this code:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?brainfeeder\.be$
RewriteRule ^/?$ /application/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /application/$1 [L]
Not sure what your question is ...
But here is an .htaccess that should accomplish what you want:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
You dont need to edit .htaccess. You just need to move the Yii entry script (index.php) and the default .htaccess up from the subdirectory to the webroot (so that they reside directly under public_html). After you move index.php and .htaccess to the root directory, all web requests will be routed directly to index.php under webroot (rather than to the subdirectory), thus eliminating the /subdirectory part of the url.
After moving the files, you will need to edit index.php to update the references to the yii.php file (under the Yii framework directory) as well as the Yii config file (main.php). Lastly, you will need to move the assets directory to directly the webroot, since by default, Yii expects the assets directory to be located in the same location as the entry script).
That should be all you need to do, but if you need more details I describe the approach more fully here:
http://muhammadatt.tumblr.com/post/83149364519/modifying-a-yii-application-to-run-from-a-subdirectory

Rewrite pagerequests to index.php, filerequests to app/webroot directory

Hey, I've been reading StackOverflow.com for a long time but decided to sign up to ask a question. I'm writing my own lightweight MVC framework that routes page requests in index.php.
Page requests look like /controller/action/arg1/arg2/arg3, and they should be rewritten to index.php?route=[request]. So, a [request] like site.com/user/profile/123 should be rewritten to index.php?route=user/profile/123
However, files aren't meant to rewrite to index.php. Assets such as images and stylesheets are in the /app/webroot/ folder, and don't need PHP to be executed. So, the mod_rewrite engine should rewrite any filerequests to /app/webroot/, and serve the configured 404 ErrorDocument when the file doesn't exist.
Directory structure
./index.php
./app/webroot/scripts/helpers/hamster.js
./app/webroot/images/logo.png
./app/webroot/style/main.css
Since you can tell the difference between a file request (/squirrel.png) and a page request (/user/profile/123) just by the existence of the file extension / dot, I was expecting that this would be really easy. But... I'm having a really hard time with it and I was hoping someone could help me out.
Something I've tried was...
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ app/webroot/$1 [L]
RewriteRule ^(.*)$ index.php?route=$1 [QSA,L]
... but it doesn't really work except for redirecting correctly to existing files. Pagerequests or nonexisting files result in HTTP 500 errors.
Any help is greatly appreciated! =)
See if this works out a little more like you expected:
RewriteEngine On
# These two lines are very specific to your current setup, to prevent
# mod_dir from doing what it does, but in a more controlled way
RewriteCond %{THE_REQUEST} ^[A-Z]+\s/iceberg[^/]
RewriteRule .* http://localhost/iceberg/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/app/webroot
RewriteCond %{REQUEST_URI} \.[a-z]+$ [NC]
RewriteRule ^.*$ app/webroot/$0 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/app/webroot
RewriteRule ^.*$ index.php?route=$0 [QSA,L]
Also, to explain, the reason why you are getting the 500 error is likely because of your rule:
RewriteRule ^(.*)$ index.php?route=$1 [QSA,L]
Since it's unconditional, and the regular expression pattern will always match, your rewrite will be performed over and over (the L flag doesn't prevent this, because after you rewrite to index.php, an internal redirection is made inside of Apache, and the process loses its current state).

Categories