Trouble with a complex rewrite

Igor Sysoev is at rambler-co.ru
Mon Apr 2 23:47:02 MSD 2007


On Mon, Apr 02, 2007 at 03:15:12PM -0400, Wilson Bilkovich wrote:

> On 4/2/07, Igor Sysoev <is at rambler-co.ru> wrote:
> >On Mon, Apr 02, 2007 at 07:41:09AM -0400, Wilson Bilkovich wrote:
> >
> >> I am migrating an existing Apache 2.2.4 -> Mongrel configuration to 
> >Nginx.
> >> Everything is working fine save for one final piece.
> >>
> >> We have a complicated rule that redirects some traffic to a partner
> >> site based on the contents of the query string. At the moment, this is
> >> still a requirement, and I can't do away with it.
> >>
> >> The existing Apache rule is:
> >>
> >> RewriteCond %{QUERY_STRING} message=.*(%\d+|\b)(foo|bar|baz|qux)(%\d+|\b)
> >> [NC]
> >> RewriteRule ^/api/receive
> >> http://target.example.com/horrible/url/?%{QUERY_STRING} [P,L,NC]
> >>
> >> The nasty piece here is that "%\d+" in the regexp pattern is
> >> necessary. 'foo' should only match if it is a whole word in the query
> >> string.
> >> (%\d+|\b) allows the pattern to handle either normal word boundaries,
> >> or HTML-encoded entities like %20.
> >> For example:
> >> api/receive?message=foo%20hello should match this rule, but:
> >> api/receive?message=hellofoo should not
> >>
> >> Is it possible to duplicate this in nginx?
> >> Thus far I have tried:
> >> 1. Making a location {} entry for api/receive, and using if
> >> ($query_string ~ pattern)
> >> 2. Using if($query_string) inside the / location block
> >> 3. Making a location entry for the regexp on its own
> >> 4. Testing with simply message=.*foo as the pattern, which makes me
> >> think the problem is more basic than the regexp pattern
> >>
> >> None of these seem to work.
> >> I've tried both "~" and "~*" styles, though I haven't actually been
> >> able to figure out what the difference between them is.
> >
> >        location /api/receive {
> >            if ($args ~ "message=.*(%\d+|\b)(foo|bar|baz|qux)(%\d+|\b)") {
> >                rewrite  ^   http://target.example.com/horrible/url/;
> >            }
> >        }
> >
> 
> Thank you for the reply.
> That syntax will do a 302 redirect though, correct? I need to actually
> proxy the request to the target server.

Sorry, I missed [P,...]. You should use

     location /api/receive {
         if ($args ~ "message=.*(%\d+|\b)(foo|bar|baz|qux)(%\d+|\b)") {
             rewrite  ^   /horrible/url/;
             break;

             proxy_pass  http://target.example.com;
         }
     }

> The "~" operator means 'does this pattern occur in the string'.. How
> does ~* differ from that? I've seen the two operators used in
> examples.

"~" means case-sensitive pattern while "~*" means case-insensitive pattern.
The wiki should be fixed.


-- 
Igor Sysoev
http://sysoev.ru/en/





More information about the nginx mailing list