Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple RewriteRules for single RewriteCond in .htaccess

I have following command in my .htaccess

    RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
    RewriteRule ^(.*?)-([a-z]+) %2/$1.$2 [L]
    RewriteRule ^(.*?)-([0-9]+)([a-z]) %2/$1$3.$2 [L]

%2 is not working in second and later lines. Can I define any variable for %2 and use it in all RewriteRule commands? Following command works

     RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
     RewriteRule ^(.*?)-([a-z]+) %2/$1.$2 [L]
     RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
     RewriteRule ^(.*?)-([0-9]+)([a-z]) %2/$1$3.$2 [L]

But I want use %2 for multiple rule line without duplicating condition.

like image 794
Huseyin Avatar asked Aug 28 '11 00:08

Huseyin


People also ask

What is rewrite rule in htaccess?

htaccess rewrite rules can be used to direct requests for one subdirectory to a different location, such as an alternative subdirectory or even the domain root. In this example, requests to http://mydomain.com/folder1/ will be automatically redirected to http://mydomain.com/folder2/.

What is NC in RewriteCond?

The [NC] specifies that the http host is case insensitive. The escapes the "." - because this is a special character (normally, the dot (.) means that one character is unspecified). The final line describes the action that should be executed: RewriteRule ^(.*)$ http://www. example.com/$1 [L,R=301]

What is RewriteCond in Apache?

RewriteCond is an apache mod-rewite directive which is used for conditional URL rewriting on Apache server. We use RewriteCond along with RewriteRule%{HTTP_HOST} , %{HTTPS} etc.


4 Answers

You can use the RewriteRule flag S|skip to tie multiples RewriteRules to a single RewriteCond (or to a set of RewriteConds). Here is an example that applies one Cond to three Rules:

RewriteCond  %{HTTP_HOST}  !^www.mydomain.com$
# skip rules if NOT within domain - only way to tie multiple rules to one cond
RewriteRule  .?  -  [S=3]
RewriteRule  ^path1(/.*)$  /otherpath1$1
RewriteRule  ^path2(/.*)$  /otherpath2$1
RewriteRule  ^path3(/.*)$  /otherpath3$1

To change an existing Cond to work for multiple Rules you have to:

  • Negate the condition (prepend it with !)
  • If you have multiple RewriteConds:
    Change logical ANDs in the Conds to ORs and vice versa.
  • Add a skipping rewrite rule in front of all rules that you want to tie to the condition(s). Set the S parameter to the number of Rule lines to be skipped.

Please be aware that it is not possible to use any backreferences that point back to the RewriteCond (like %1) in the skipped Rules. These are only accessible in the skipping RewriteRule.

like image 106
Jpsy Avatar answered Sep 30 '22 14:09

Jpsy


The variable must be saved as an Apache var, then that can be used without repeated conditions.

Saving in Apache variables are shown in second line. Usage of saved vars in 3th and 4th lines.

RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC]
RewriteRule .? - [E=Wa:%1,E=Wb:%2]
RewriteRule ^(.*?)-([a-z]+) %{ENV:Wb}/$1.%{ENV:Wb} [L]
RewriteRule ^(.*?)-([0-9]+)([a-z]) %{ENV:Wb}/$1$3.$2 [L]
like image 40
Huseyin Avatar answered Sep 30 '22 12:09

Huseyin


Clearly, this isn’t much fun, especially as things grow and become more complex. However, there is a less well known option of the RewriteRule statement, that tells apache to skip the next N number of RewriteRule statement. [S=N]. So instead of checking each time if the request is NOT a file AND is NOT a directory, we could do this: Code block

#
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [S=3]
RewriteRule ^([^./]+)/$ http://www.santweb.co.uk/$1 [L]
RewriteRule ^([^./]+)/([^./]+)/$ http://www.santweb.co.uk/$1/$2 [L]
RewriteRule ^([^./]+)/([^./]+)/([^./]+)/$ http://www.santweb.co.uk/$1/$2/$3 [L]

#

I found this, from: http://www.sant-media.co.uk/2010/03/applying-rewritecond-to-multiple-rewriterule-in-htaccess/

I think it helpfull

like image 26
Hoàng Vũ Tgtt Avatar answered Sep 30 '22 14:09

Hoàng Vũ Tgtt


From Apache 2.4 you can use the <If> directive:

RewriteEngine On
<If "%{HTTP:Upgrade} == 'websocket'">
    RewriteRule /nidoran/(.*)           ws://localhost:8080/nidoran/$1 [P,L]
    RewriteRule /kakuna/(.*)           ws://localhost:8081/kakuna/$1 [P,L]
    RewriteRule /porygon/(.*)           ws://localhost:8082/porygon/$1 [P,L]
</If>

http://httpd.apache.org/docs/2.4/expr.html#examples

like image 21
Juan Calero Avatar answered Sep 30 '22 14:09

Juan Calero