2

As some background, I'm trying to fix requests that are coming in with duplicated params e.g:

/products/compare/?ids=554?ids=554
/products/compare/?ids=595,662,726?ids=595,662,726

My fix - which works - looks like this:

location /products/compare/ {
    if ( $args ~ "(ids=[\d,]+)\?ids=[\d,]+" ) {
        set $id $1;
        rewrite ^.*$ $scheme://$host/$uri$is_args$id? permanent;
    }
}

My question is regarding the set $id $1;, and why it's necessary

I was using the $1 capture-group variable directly in the rewrite:

rewrite ^.*$ $scheme://$host/$uri$is_args$1? permanent;

But the variable wasn't being populated.

Why not?

1
  • Just to clarify, when you use the set command, the variable does populate? btw, nice name :) Commented Jul 17, 2018 at 17:34

1 Answer 1

6

The first parameter of the rewrite directive is a regular expression which may contain numbered captures. As a result, all numbered captures are reset when the rewrite statement is entered.

As an alternative to using the set directive, you could use a named capture within your if statement's regular expression.

For example:

if ( $args ~ "(?<id>ids=[\d,]+)\?ids=[\d,]+" ) {
    rewrite ^ $scheme://$host/$uri$is_args$id? permanent;
}

Of course, you do not actually need to use rewrite. If you use return instead, the numeric capture remains in scope.

For example:

if ( $args ~ "(ids=[\d,]+)\?ids=[\d,]+" ) {
    return 301 $scheme://$host/$uri$is_args$id;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks. And yes, good point about return rather than rewrite.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.