fygesser fygesser - 3 months ago 13
Apache Configuration Question

Multiple RewriteRules for a single URL

I want to use multiple

RewriteRules
in
.htaccess
to modify a single URL, but only the last rule gets applied.

Example INPUT (link loaded by a browser):

http://example.com/aaa/foo/bar


.htaccess:

RewriteRule ^(.*)foo/(.*)$ $1nofoo/$2
RewriteRule ^(.*)bar(.*)$ $1nobar$2


EXPECTED OUTPUT (what Apache should actually look at):

http://example.com/aaa/nofoo/nobar


ACTUAL OUTPUT:

http://example.com/aaa/foo/nobar/


As you can see, only the last rule was applied. Is there any way to make it work the way I want? All suggestions are welcome.

PS. I want to avoid creating a static, ugly rule like

^(.*)foo/bar(.*) $1nofoo/nobar$2


I need all the modifications to work independently of each other.

UPDATE

So here is exactly what I am trying to achieve. I have some links to a backend server:

http://myserver.com/api/user/$userid/car/$carid/getSpeedRecordDetails
http://myserver.com/api/user/$userid/getUserDetails
http://myserver.com/api/car/$carid/getCarDetails


Where $userid and $carid are some unique 12-char-long strings.

And I want to transform them to these:

http://myserver.com/api/getSpeedRecordDetails.php?userid=$userid&carid=$carid
http://myserver.com/api/getUserDetails.php?userid=$userid
http://myserver.com/api/getCarDetails.php?carid=$carid


And I want to achieve it using the least RewriteRules possible (I am looking for a dynamic solution).

UPDATE #2

I love the SO community! Your patience and willingness to help is truly amazing :)

So the very reason why I am interested in modifying the URL using multiple RewriteRules is because I expect that my backend might soon need to implement hundreds (if not thousands) of user-friendly URLs, and mapping all of them individually would be a waste of time and money. Therefore, I want to take advantage of the fact that all the user-friendly URLs consist of repetitive chunks that can be easily translated. The calls below represent the general three types of the user-friendly URLs I need to manage. The only difference within each type is $userid, $carid, and XXXX_of_a_thousand_functions.

http://myserver.com/backend-api/user/$userid/car/$carid/first_of_a_thousand_functions.do
http://myserver.com/backend-api/user/$userid/second_of_a_thousand_functions.do
http://myserver.com/backend-api/car/$carid/sixteenth_of_a_thousand_functions.do


All of these calls (and remember, there will be hundreds, or even thousands of them) need to be translated into these:

http://myserver.com/backend-api/first_of_a_thousand_functions.php?USER_ID=$userid&CAR_ID=$carid
http://myserver.com/backend-api/second_of_a_thousand_functions.php?USER_ID=$userid
http://myserver.com/backend-api/sixteenth_of_a_thousand_functions.php?CAR_ID=$carid


Seeing that there is a simple pattern governing the translation (I hope it is also visible to you), I thought I could create some simple rules for translating different 'chunks' of the user-friendly URL into the internal URL. For example:

RewriteRule ^(.*)user/([A-Za-z0-9]+)/(.*)$ $1$3&USER_ID=$2


Would be responsible for translating the piece
user/HSGRE8563LOS
into
&USER_ID=HSGRE8563LOS


And because some calls have more than one 'chunk' to process, I need to be able to use multiple RewriteRules on a single URL, which I hope somewhat correlates with the title of the question :)

Answer

After UPDATE#1... to internally rewrite from the stated friendly URLs using mod_rewrite. Try the following directives in the root .htaccess file:

RewriteEngine On

# http://myserver.com/api/user/$userid/car/$carid/getSpeedRecordDetails
RewriteRule ^api/user/(\w{12})/car/(\w{12})/(getSpeedRecordDetails)$ /api/$3.php?userid=$1&carid=$2 [L]

# http://myserver.com/api/user/$userid/getUserDetails
RewriteRule ^api/user/(\w{12})/(getUserDetails)$ /api/$2.php?userid=$1 [L]

# http://myserver.com/api/car/$carid/getCarDetails
RewriteRule ^api/car/(\w{12})/(getCarDetails)$ /api/$2.php?carid=$1 [L]

\w{12} matches a 12 char long string of letters (upper/lower), numbers and underscore. However, this should be made as restrictive as possible. eg. if a valid id is only numeric then \d{12} would be preferable.

UPDATE#2 The process is almost the same as above....

RewriteBase /backend-api

# http://myserver.com/backend-api/user/$userid/car/$carid/<any>.do
RewriteRule ^backend-api/user/(\w{12})/car/(\w{12})/(\w+)\.do$ $3.php?USER_ID=$1&CAR_ID=$2 [L]

# http://myserver.com/backend-api/user/$userid/<any>.do
RewriteRule ^backend-api/user/(\w{12})/(\w+)\.do$ $2.php?USER_ID=$1 [L]

# http://myserver.com/backend-api/car/$carid/<any>.do
RewriteRule ^backend-api/car/(\w{12})/(\w+)\.do$ $2.php?CAR_ID=$1 [L]

Note the use of RewriteBase. This allows the URL-path to be removed from the RewriteRule substitution.

If /backend-api exists as a physical directory then these rules could instead go in /backend-api/.htaccess. Then you could remove the RewriteBase directive and modify the RewriteRule pattern by removing the backend-api/ portion from near the start of the pattern.