views:

78

answers:

2

Here is my .htaccess file

Options +FollowSymlinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !=cms

RewriteRule ^([^/]*)/search/([^/]+)$  index.php?lang=$1&id=search&searchword=$2 [L]
RewriteRule ^([^/]*)/([^/]*)$  index.php?lang=$1&id=$2 [L]

It doesn't work as i expect.

My .css,.js files has absolute path, like http://bs.am/finance/css/style.css (my all files in finance folder)

The first rule breaks all css and js files, but if i replace the places of rewriteRules, works fine.

Could somebody explain such behavior?

I also tried RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$ but doesn't help.

Thanks much

+1  A: 

Based on your question, it seems that your .htaccess file is in the /finance/ folder. If this is the case, the problem lies in the fact that your second RewriteRule will match the requests for your scripts and sylesheets.

The conditions you have already will allow you to avoid this problem, but they only apply to the first rule that comes after them (your search rule). As usual, there are a few different ways to fix things, but the simplest is to copy your RewriteCond block so that it applies to the second rule too. This would look like the following:

Options +FollowSymlinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 =cms
RewriteRule ^([^/]*)/search/([^/]+)$  index.php?lang=$1&id=search&searchword=$2 [L]

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !=cms
RewriteRule ^([^/]*)/([^/]*)$  index.php?lang=$1&id=$2 [L]

Note that you might not even need the condition block for the first rule, as it's probably unlikely that any of your real files match that test pattern. It is definitely needed on the second one though, to prevent your resources from being misdirected.

Alternative Approach

Options +FollowSymlinks
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond $1 !=cms
RewriteRule ^([^/]*) - [S=2]

RewriteRule ^([^/]*)/search/([^/]+)$  index.php?lang=$1&id=search&searchword=$2 [L]
RewriteRule ^([^/]*)/([^/]*)$  index.php?lang=$1&id=$2 [L]

In this approach, if any of your conditions match, we skip the next two rules (indicated by the S=2. This is the same as applying the condition block to both of them. As Gumbo mentions, you could also use the L flag in place of the S=2 to ignore every rule that comes after that block in the case of your conditions matching. Which of these options is most appropriate depends on what other rules you might want to add in the future.

Tim Stone
Thanks much Tim, but why it's needed to write `RewriteCond` for each `RewriteRule`? Isn't there any way, to wrote `RewriteCond` which will applies to all rules?
Syom
@Syom: A block of `RewriteCond` only apply to the next `RewriteRule`, because the mod_rewrite engine has no way of knowing that you no longer want to apply those conditions (there's no "end if" statement). So, as a result, you have to apply it to each rule, or invert the condition so you can prevent processing rules after the condition block.
Tim Stone
+1  A: 

A RewriteCond directive does only belong to the next following RewriteRule. So your three RewriteCond directives do only belong to the first RewriteRule but not to the second that has no conditions.

So to exclude existing files and directories for the second RewriteRule, you would need to write the same RewriteConds in front of your other rule too:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !=cms
RewriteRule ^([^/]*)/search/([^/]+)$  index.php?lang=$1&id=search&searchword=$2 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !=cms
RewriteRule ^([^/]*)/([^/]*)$  index.php?lang=$1&id=$2 [L]

But you can also use a rule that stops the rewriting process when the request can be mapped onto an existing file or directory:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

Put this rule in front of your other rules and the rewriting process will stop with this rule.

Gumbo
@Gumbo Thanks much. Explain the last RewriteRule please. What does it mean - `^ - [L]` ?
Syom
@Syom: `^` is the pattern, `-` the substitution and `[L]` are the flags: `^` matches any request, `-` indicates that no substitution should be performed and `[L]` indicates that this is the last rule that should be tested.
Gumbo