views:

249

answers:

1

I'd like to use AliasMatch to create an alias for everything within a folder, except for two (or more) specific regex patterns.

For instance the following AliasMatch creates an alias for everything in the 'content' folder:

AliasMatch /content(.*) /home/username/public_html/$1

But there are two regex patterns that I don't want the above Alias to match, for instance:

^content/([a-zA-Z0-9_-]+)/id-([a-zA-Z0-9_-]+)/([0-9]+)
^content/([a-zA-Z0-9_-]+)/nn-([a-zA-Z0-9_-]+)

I know that the NOT (!) character can be used to negate a pattern, but I don't know how to use it here, or how to negate multiple patterns in AliasMatch.

How could this be done?

+1  A: 

What you're talking about is called negative lookahead, and you just wrap it around the regex for what you don't want to match, like this: (?!foo). Combining regexes can be as simple as string them together with a pipe between them, but you can do a little better than that in this case. This regex reuses the first part of the two regexes, which is identical:

[a-zA-Z0-9_-]+/(?:id-[a-zA-Z0-9_-]+/[0-9]+|nn-[a-zA-Z0-9_-]+)

Because the pipe (or '|', the alternation operator) has lower precedence than anything else, the alternation has to be contained in a group. Notice that I used a non-capturing group -- i.e., (?:...) -- and got rid of the parentheses in your regexes. Otherwise, they would have thrown off the numbering of the one group you do want to capture, and you would have had to use something other than $1 in the second part of the rule. Here's the whole regex:

^/content(?![a-zA-Z0-9_-]+/(?:id-[a-zA-Z0-9_-]+/[0-9]+|nn-[a-zA-Z0-9_-]+))(.*)

EDIT: Apparently, the regex flavor used by AliasMatch doesn't support lookaheads, but has its own negation syntax: !(^/foo). Its purpose seems to be to negate the whole regex, which means it wouldn't help you, but maybe you don't need it. Maybe you can just alias those directories to themselves. Then you wouldn't have to negate anything.

AliasMatch ^(/content/[a-zA-Z0-9_-]+/id-[a-zA-Z0-9_-]+/[0-9]+.*) $1
AliasMatch ^(/content/[a-zA-Z0-9_-]+/nn-[a-zA-Z0-9_-]+.*) $1
AliasMatch ^/content/(.*) /home/username/public_html/$1

Or maybe you can do something with a <DirectoryMatch> directive, or by switching to mod_rewrite. But I'm (obviously) not an Apache expert--my specialty is regexes, and I don't think a regex is going to solve your problem.

Alan Moore
Thank you very much :) However after I copied what you gave into my httpd.conf (as "AliasMatch [regex] /home/username/public_html/$1"), httpd no longer compiles - it gives a "Regular expression could not be compiled." syntax error. What would be the problem here? Am I using it wrong?
Tristan
The problem seems to be with the lookahead - httpd.conf doesn't seem to be able to parse it?
Tristan
You're right--see my edit.
Alan Moore