Apache Alias和多个版本的代码库

I am trying to run a versioned API from separate directories outside my Apache doc root.

My current approach is to try this with the Alias directive:

Alias /api/v1.2/ /var/www/api-v1.2/
Alias /api/v1.1/ /var/www/api-v1.1/

This is working fine, however I am using a PHP framework (Codeigniter) that uses mod_rewrite to route all requests to my index.php front controller:

RewriteCond %{REQUEST_URI} !=/server-status
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/?$1 [L]

I can access actual files via the URL, and the alias directive works fine. When I access a URL that the system means to rewrite, the request is served from the doc root.

How can I get my CI application to follow the Alias rules while still routing traffic to each respective front controller?

EDIT: to be clear, I have 3 separate versions of my CI codebase: 1 in the Apache doc root, and 2 others in each aliased directory. I want to route requests to the correct version of the codebase based on the URL (defaulting to the doc root if no Alias is matched).

/var/www/html (doc root)
/var/www/api-v1.2
/var/www/api-v1.1

So, the problem is that you aren't preventing your initial .htaccess from rewriting the folders.

You will need 3 .htaccess files, one in the root and one in each of the v1.1 and v1.2 folders.

Root (docroot):

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !=/server-status
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|robots\.txt|api/v1.1|api/v1.2)
RewriteRule ^(.*)$ index.php/$1 [L]

The important line being the last RewriteCond where it tells apache to ignore the api folders.

api-v1.1 folder:

RewriteEngine on
RewriteBase /api/v1.1
RewriteCond %{REQUEST_URI} !=/server-status
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

api-v1.2 folder:

RewriteEngine on
RewriteBase /api/v1.2
RewriteCond %{REQUEST_URI} !=/server-status
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

The important lines being RewriteBase. This tells apache the directory we're working in and will process the rewrites based on its designation.

So, I think this is pretty straightforward. You want to make sure the set of rewrite conditions (RewriteCond) are not matched in one case - when they start with "/api" or "api" - so they don't fire the rewrite rule.

So, just add this line at the top of the CodeIgniter rewrite conditions:

RewriteCond %{REQUEST_URI} !(^(/)?api)

That will prevent that set of conditions from being matched when your request URI (the part after the "http://example.com/") starts with /api or api. Any request URI that doesn't match /api or api WILL fire the CodeIgniter rules.

There are two secrets to mod_rewrite:
1) It breaks up the incoming request into tokens: the HTTP_HOST(e.g. "http://example.com"), the REQUEST_URI (the part after the http://example.com - like say, /index.php) and optional QUERY_STRING (the part after a ? in "http//example.com/index.php?test=3").

2) Then you can use perl regular expressions to match those tokens and rewrite the url to point to a resource or really, do any number of URL rewrites or substitutions.

References:
1) Rewrite tutorial: http://httpd.apache.org/docs/2.2/rewrite/intro.html
2) Rewrite reference: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
3) Regular expression cheat sheet: http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/