Maintain separate .htaccess files in sub-folder - .htaccess

How do I maintain 2 separate .htaccess files so as to avoid dumping rules in the main .htaccess file.
For example: I want all the urls trailing after ^shows(/.*)?$ to point to .htaccess created under controllers/shows (.htaccess)

Depending on your rewrite rules, this can be accomplished with minimal rewriting (heh) of the .htaccess file. Take for example this .htaccess file stored in the webroot /var/www/html:
RewriteEngine On
RewriteRule ^/foo/help/(.*)? /foo/help.php?q=$1
Rewriterule ^blog/(.*)? blog/index.php?id=$1
We're doing two kinds of rewrite here:
www.example.com/foo/help/123 -> wwww.example.com/foo/help.php?q=123
www.example.com/blog/myarticle -> www.example.com/blog/index.php?id=myarticle
Notice the first RewriteRule is using absolute paths, while the second is using a relative path.
If I were to move the first RewriteRule into /var/www/html/foo/.htaccess, the file would look like this:
RewriteEngine On
RewriteRule ^/foo/help/(.*)? /foo/help.php?q=$1
Note that nothing needs to change, since you're using an absolute path.
Now if I were to move the second RewriteRule into /var/www/html/blog/.htaccess, the file would look like this:
RewriteEngine On
RewriteBase /blog/
RewriteRule ^(.*)? index.php?id=$1
Note the paths in the RewriteRule were stripped to make them relative to the current directory, which is now /blog. Also note the RewriteBase directive, which is necessary when using relative rewrite rules in a subdirectory.
Check out this question for another example of using subdirectory .htaccess rewrite rules.

Related

.htaccess rewrite root folder to subfolder

Please could I have some help redirecting URLs to a subfolder so that everything in https://example.com is rewritten to https://example.co.uk/subfolder?
The .htaccess file needs to be in /subfolder.
You could do something like the following in the root .htaccess file to rewrite all direct requests to the subfolder.
RewriteEngine On
# Rewrite all direct requests to the `/subfolder` directory
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ subfolder%{REQUEST_URI} [L]
The check against the REDIRECT_STATUS environment variable ensures that only direct requests from the client (as opposed to internally rewritten requests) are rewritten to the /subfolder directory (thus avoiding a rewrite loop).
This also means that a direct request for /subfolder itself will also be rewritten to the /subfolder directory (ie. /subfolder/subfolder) - so you can have a sub-subfolder of the same name if you wish (otherwise direct requests for /subfolder will result in a 404). That is, unless you have an additional .htaccess file in the subfolder that also contains mod_rewrite directives, in which case these directives will be overridden.
UPDATE: Following your question update that now states the following...
The .htaccess file needs to be in /subfolder.
In that case, this is not possible. The .htaccess file that rewrites requests to the /subfolder must be in the document root (the parent directory).
If the .htaccess file is in the /subfolder itself then it will simply never be processed for requests outside of that subfolder in order to rewrite the request.
MrWhite already gave nearly all the explanation I should have attached to my answer. So, like he already stated in his answer, the directives given below should be written into the .htaccess file that is located in the folder where https://site1.co.uk points to for it to work as you expect.
Here are the directives you can use.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /subfolder/$1 [QSA,L]
</IfModule>
The first RewriteCond will help make sure that the request is not for a file that already exists in the folder that the .htaccess file is located.
The second RewriteCond line is similar to the first but this checks for a folder instead. After this line, you can, and probably should, add the REDIRECT_STATUS line from MrWhite's answer. See his answer for the explanation.
The RewriteRule line uses Regular Expressions (RegEx) to effect the rewrite. Remember to replace subfolder on this line to name of the folder you wish to use and this folder should exist in the same location that the .htaccess file is located, and like already explained, this must be the folder that https://site1.co.uk points to.
Hope this helps.

Rewrite multiple sub-directories to the same path htaccess

I want to rewrite multiple sub-directories to the same path. while I can remove a part from URL Apache htaccess
for example, I want
domain.com/category/computer/internet-topics
domain.com/category/computer/windows-topics
domain.com/category/science/physics-topics
domain.com/category/science/biology-topics
to be
domain.com/category/internet-topics
domain.com/category/windows-topics
domain.com/category/physics-topics
domain.com/category/biology-topics
When I use this, it works fine for the first line only (computer)
RewriteEngine On
RewriteRule ^category/([a-zA-Z0-9_-]+)$ category/computer/$1
RewriteRule ^category/([a-zA-Z0-9_-]+)$ category/science/$1
I think you need to be specific else only first rule will be used
RewriteEngine On
RewriteRule ^category/((internet)|(windows)-topics)$ category/computer/$1
RewriteRule ^category/((physics)|(biology)-topics)$ category/science/$1

htacces rewrite single file

I want to rewrite a specific file on my website to another one by using htaccess:
# General
RewriteEngine On
RewriteBase /
Options All -Indexes
Options +FollowSymLinks
# Rewrite file
RewriteRule ^/file.html$ /dir/file.html [L]
This is the .htaccess code i'm using based on snippets i found on the internet.
Somehow this is not working, the server is returning a 404-Not-found error.
I can't see any difference with example's that are said to work, like in
Rewriting path for a specific file using htaccess
Edit:
If I place file.html in the root-folder, I can view it. So the rewrite definitely is not happening.
RewriteRule does not receive leading slash. Write so:
RewriteRule ^file.html$ /dir/file.html [L]

htaccess - rewrite URL to make querystring nice

I have a site with a folder, and a htaccess file within that folder. For the index.php file within that folder, I want to rewrite the querystring for a certain parameter, so that typing in this URL:
www.example.com/myfolder/myparameter
Behaves like this (ie makes $_GET['parameter'] = 'myparameter' in my code)
www.example.com/myfolder/index.php?parameter=myparameter
I have looked at many questions on StackOverflow, but have not managed to get this working. My code so far is
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*) [NC]
RewriteRule ^$ %0 [QSA]
But that just isn't working at all.
Please use this code
RewriteEngine on
RewriteRule (.*) index\.php?parameter=$1 [L,QSA]
RewriteEngine on
RewriteRule (^.*/)([^/]+)$ $1index\.php?parameter=$2 [L,QSA]
update
sorry use #somasundaram's answer. Per-directory .htaccess rewrite rules lose the directory prefix:
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the RewriteRule pattern matching and automatically added after any relative (not starting with a slash or protocol name) substitution encounters the end of a rule set. See the RewriteBase directive for more information regarding what prefix will be added back to relative substitutions.
(from the apache docs)

How does RewriteBase work in .htaccess

I have seen this in a few .htaccess examples
RewriteBase /
It appears to be somewhat similar in functionality to the <base href=""> of HTML.
I believe it may automatically prepend its value to the beginning of RewriteRule statements (possibly ones without a leading slash)?
I could not get it to work properly. I think it's use could come in very handy for site portability, as I often have a development server which is different to a production one. My current method leaves me deleting portions out of my RewriteRule statements.
Can anyone explain to me briefly how to implement it?
Thanks
RewriteBase is only applied to the target of a relative rewrite rule.
Using RewriteBase like this...
RewriteBase /folder/
RewriteRule a\.html b.html
is essentially the same as...
RewriteRule a\.html /folder/b.html
But when the .htaccess file is inside /folder/ then this also points to the same target:
RewriteRule a\.html b.html
Although the docs imply always using a RewriteBase, Apache usually detects it correctly for paths under the DocumentRoot unless:
You are using Alias directives
You are using .htaccess rewrite rules to perform HTTP redirects (rather than just silent rewriting) to relative URLs
In these cases, you may find that you need to specify the RewriteBase.
However, since it's a confusing directive, it's generally better to simply specify absolute (aka 'root relative') URIs in your rewrite targets. Other developers reading your rules will grasp these more easily.
Quoting from Jon Lin's excellent in-depth answer here:
In an htaccess file, mod_rewrite works similar to a <Directory> or <Location> container. and the RewriteBase is used to provide a relative path base.
For example, say you have this folder structure:
DocumentRoot
|-- subdir1
`-- subdir2
`-- subsubdir
So you can access:
http://example.com/ (root)
http://example.com/subdir1 (subdir1)
http://example.com/subdir2 (subdir2)
http://example.com/subdir2/subsubdir (subsubdir)
The URI that gets sent through a RewriteRule is relative to the directory containing the htaccess file. So if you have:
RewriteRule ^(.*)$ -
In the root htaccess, and the request is /a/b/c/d, then the captured URI ($1) is a/b/c/d.
If the rule is in subdir2 and the request is /subdir2/e/f/g then the captured URI is e/f/g.
If the rule is in the subsubdir, and the request is /subdir2/subsubdir/x/y/z, then the captured URI is x/y/z.
The directory that the rule is in has that part stripped off of the URI. The rewrite base has no affect on this, this is simply how per-directory works.
What the rewrite base does do, is provide a URL-path base (not a file-path base) for any relative paths in the rule's target. So say you have this rule:
RewriteRule ^foo$ bar.php [L]
The bar.php is a relative path, as opposed to:
RewriteRule ^foo$ /bar.php [L]
where the /bar.php is an absolute path. The absolute path will always be the "root" (in the directory structure above). That means that regardless of whether the rule is in the "root", "subdir1", "subsubdir", etc. the /bar.php path always maps to http://example.com/bar.php.
But the other rule, with the relative path, it's based on the directory that the rule is in. So if
RewriteRule ^foo$ bar.php [L]
is in the "root" and you go to http://example.com/foo, you get served http://example.com/bar.php. But if that rule is in the "subdir1" directory, and you go to http://example.com/subdir1/foo, you get served http://example.com/subdir1/bar.php. etc. This sometimes works and sometimes doesn't, as the documentation says, it's supposed to be required for relative paths, but most of the time it seems to work. Except when you are redirecting (using the R flag, or implicitly because you have http://host in your rule's target). That means this rule:
RewriteRule ^foo$ bar.php [L,R]
if it's in the "subdir2" directory, and you go to http://example.com/subdir2/foo, mod_rewrite will mistake the relative path as a file-path instead of a URL-path and because of the R flag, you'll end up getting redirected to something like: http://example.com/var/www/localhost/htdocs/subdir1. Which is obviously not what you want.
This is where RewriteBase comes in. The directive tells mod_rewrite what to append to the beginning of every relative path. So if I have:
RewriteBase /blah/
RewriteRule ^foo$ bar.php [L]
in "subsubdir", going to http://example.com/subdir2/subsubdir/foo will actually serve me http://example.com/blah/bar.php. The "bar.php" is added to the end of the base. In practice, this example is usually not what you want, because you can't have multiple bases in the same directory container or htaccess file.
In most cases, it's used like this:
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
where those rules would be in the "subdir1" directory and
RewriteBase /subdir2/subsubdir/
RewriteRule ^foo$ bar.php [L]
would be in the "subsubdir" directory.
This partly allows you to make your rules portable, so you can drop them in any directory and only need to change the base instead of a bunch of rules. For example if you had:
RewriteEngine On
RewriteRule ^foo$ /subdir1/bar.php [L]
RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L]
RewriteRule ^blah2$ /subdir1/blah2.php [L]
...
such that going to http://example.com/subdir1/foo will serve http://example.com/subdir1/bar.php etc. And say you decided to move all of those files and rules to the "subsubdir" directory. Instead of changing every instance of /subdir1/ to /subdir2/subsubdir/, you could have just had a base:
RewriteEngine On
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
RewriteRule ^blah1$ blah.php?id=1 [L]
RewriteRule ^blah2$ blah2.php [L]
...
And then when you needed to move those files and the rules to another directory, just change the base:
RewriteBase /subdir2/subsubdir/
and that's it.
In my own words, after reading the docs and experimenting:
You can use RewriteBase to provide a base for your rewrites. Consider this
# invoke rewrite engine
RewriteEngine On
RewriteBase /~new/
# add trailing slash if missing
rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]
This is a real rule I used to ensure that URLs have a trailing slash. This will convert
http://www.example.com/~new/page
to
http://www.example.com/~new/page/
By having the RewriteBase there, you make the relative path come off the RewriteBase parameter.
AFAIK, RewriteBase is only used to fix cases where mod_rewrite is running in a .htaccess file not at the root of a site and it guesses the wrong web path (as opposed to filesystem path) for the folder it is running in. So if you have a RewriteRule in a .htaccess in a folder that maps to http://example.com/myfolder you can use:
RewriteBase myfolder
If mod_rewrite isn't working correctly.
Trying to use it to achieve something unusual, rather than to fix this problem sounds like a recipe to getting very confused.
RewriteBase is only useful in situations where you can only put a .htaccess at the root of your site. Otherwise, you may be better off placing your different .htaccess files in different directories of your site and completely omitting the RewriteBase directive.
Lately, for complex sites, I've been taking them out, because it makes deploying files from testing to live just one more step complicated.
When I develop, it's on a different domain within a folder. When I take a site live, that folder doesn't exist anymore. Using RewriteBase allows me to use the same .htaccess file in both environments.
When live:
RewriteBase /
# RewriteBase /dev_folder/
When developing:
# RewriteBase /
RewriteBase /dev_folder/
The clearest explanation I found was not in the current 2.4 apache docs, but in version 2.0.
# /abc/def/.htaccess -- per-dir config file for directory /abc/def
# Remember: /abc/def is the physical path of /xyz, i.e., the server
# has a 'Alias /xyz /abc/def' directive e.g.
RewriteEngine On
# let the server know that we were reached via /xyz and not
# via the physical path prefix /abc/def
RewriteBase /xyz
How does it work? For you apache hackers, this 2.0 doc goes on to give "detailed information about the internal processing steps."
Lesson learned: While we need to be familiar with "current," gems can be found in the annals.
This command can explicitly set the base URL for your rewrites. If you wish to start in the root of your domain, you would include the following line before your RewriteRule:
RewriteBase /
I believe this excerpt from the Apache documentation, complements well the previous answers :
This directive is required when you use a relative path in a
substitution in per-directory (htaccess) context unless either of the
following conditions are true:
The original request, and the substitution, are underneath the DocumentRoot (as opposed to reachable by other means, such as Alias).
The filesystem path to the directory containing the RewriteRule, suffixed by the relative substitution is also valid as a URL path on
the server (this is rare).
As previously mentioned, in other contexts, it is only useful to make
your rule shorter. Moreover, also as previously mentioned, you can
achieve the same thing by placing the htaccess file in the
subdirectory.
I simply delete .htaccess file and it runs perfectly

Resources