Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does RewriteBase do and how to use it?

I am trying to learn some .htaccess tricks. I came across the RewriteBase directive but could not get it to work properly.

I wonder what this directive does specifically and how to use it. There have been some discussions about RewriteBase in StackOverflow and the Apache documentation but still, I could not get a clear answer to my question.

Could someone show me a simple but effective example where RewriteBase can be used?

like image 402
Chong Lip Phang Avatar asked Jan 25 '14 07:01

Chong Lip Phang


People also ask

What is RewriteBase?

RewriteBase is a useful server directive available for Apache web server that allows you to easily update numerous rewrite rules at one go.

What does IfModule mod_rewrite C mean?

The <IfModule mod_rewrite. c>... </IfModule> block ensures that everything contained within that block is taken only into account if the mod_rewrite module is loaded. Otherwise you will either face a server error or all requests for URL rewriting will be ignored.

What is mod_rewrite?

mod_rewrite is an Apache module that allows for server-side manipulation of requested URLs. mod_rewrite is an Apache module that allows for server-side manipulation of requested URLs. Incoming URLs are checked against a series of rules. The rules contain a regular expression to detect a particular pattern.


2 Answers

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:

root  |-- 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. So if you have:

RewriteRule ^(.*)$ -  

in the root, and the request is /a/b/c/d, then the captured URI ($1) is a/b/c/d. But if the rule is in subdir2 and the request is /subdir2/e/f/g then the captured URI is e/f/g. And 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 if 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] 

and that rule is 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.

like image 166
Jon Lin Avatar answered Sep 22 '22 00:09

Jon Lin


The 1 line answer is: Rewritebase sets the basepath of rewriterule arg2.

That's literally it. (so it works like html basehref, &pointint; except it's useful since often in the context of URL-rewriting the default base [.] is not wanted.)

Rewritebase makes maintenance easier if you have multiple rewriterules. Indeed, if you're only using one line of rewriterule, then rewritebase is pretty much useless (as you can simply rewriterule the based url).


Sidenote

Of course, you could ignore rewritebase completely, by using only absolute paths for rewriterules.


Related
  • a rewritebase undesigned [coincidental] use
like image 31
Pacerier Avatar answered Sep 24 '22 00:09

Pacerier