Simon
Simon

Reputation: 2433

Apache RewriteRule not substituting RewriteCond capturing group with negated pattern

I am familiar with Regexp, RewriteCond and RewriteRule.

The problem is that my RewriteRule does not substitute the capturing group from the last RewriteCond.

Apache v2.4.10

RewriteCond %{REQUEST_URI} !(apps/)?index.php
RewriteRule ^(apps/)?(.*)$ /%1index.php?$2 [QSA,NC,L]

According to the doc, the %1 should be replaced with the capturing group in the RewriteCond : (apps/) but it is not.

Apache debug:

RewriteCond: input='/apps/x/y' pattern='!(apps/)?index.php' => matched
rewrite 'x/y' -> '/index.php?x/y'

The debug indeed says that the Cond is matched and therefore it should capture the group.

It says that the input is including the apps/ part.

But then, the rewrite does not consider it...

Adding an extra (useless) RewriteCond as follows to force a match but without negating the pattern with ! does make it work, so indeed the capturing group is captured and substituted :

RewriteCond %{REQUEST_URI} !(apps/)?index.php
RewriteCond %{REQUEST_URI} ^/(apps/)?
RewriteRule ^(apps/)?(.*)$ /%1index.php?$2 [QSA,NC,L]

Any idea ? Is this some sort of optimization from the regexp with the ! such that it does not evaluate the capturing group ? Should this be reported as a bug ? Is it documented anywhere ?

Upvotes: 2

Views: 654

Answers (1)

user2493235
user2493235

Reputation:

Nothing is captured on a negated pattern because by definition the pattern did not match so there is nothing to capture. It's mentioned in the documentation but is also obvious if you think about it. How can something that wasn't there be captured? The capturing comes from the match not from the contents of the regex. It could include wild cards or other variable patterns. In your case it doesn't. If it did, what would it put in the capture? There is nothing to use. When it doesn't, you already know what it is anyway so no need to "capture" it. There is no place for capturing with negated patterns.

From the docs:

Note

When using the NOT character to negate a pattern, you cannot include grouped wildcard parts in that pattern. This is because, when the pattern does NOT match (ie, the negation matches), there are no contents for the groups. Thus, if negated patterns are used, you cannot use $N in the substitution string!

The above is from the RewriteRule section but clearly same for negated RewriteCond patterns, by definition.

Upvotes: 2

Related Questions