2

I'm trying to remove some parameters using nginx return 301.

For example I want URLs redirected like this:

https://www.example.com/one?wanted=1&unwanted1=1 -> https://www.example.com/one?wanted=1

https://www.example.com/one?unwanted1=1 -> https://www.example.com/one

https://www.example.com/one?unwanted1=1&unwanted2=2&unwanted3=3 -> https://www.example.com/one

...and so on

I did some experiments with this code (note it uses rewrite instead of return):

if ($request_uri ~ "([^\?]*)\?(.*)unwanted=([^&]*)&?(.*)") {
  set $args $2$4;

  rewrite "^" $scheme://$host$uri permanent;
}

This works well when only one of the unwanted parameters are present.

I tried to repeat it for each parameter but now it doesn't work in an optimum way as it does multiple redirects and does not clean up the "&" when it is no longer needed (only one arg left).

...moreover - I would prefer to use return 301 instead of rewrite as I understand it would be the preferred way in these kind of situations. Tried to adapt the last line to return 301 but it didn't work out for me.

Any ideas how I can correctly accomplish this?

Alex
  • 115
  • 10
  • Possible duplicate of [nginx 301 redirect with query string](https://stackoverflow.com/questions/40810219/nginx-301-redirect-with-query-string) – erik258 Dec 15 '17 at 22:19
  • I didn't notice that you've been editing your question (the notification is missing for some reason). I will have another look at this. – Richard Smith Dec 16 '17 at 10:32
  • I didn't edit the question itself. I only edited the comments for your answer. Unfortunately these comments can't be properly formatted, [enter] posts the comment and you only have 5 minutes to edit. So... it was not really organised :) – Alex Dec 16 '17 at 10:46
  • Ok, in that case I didn't read your question properly. Hopefully my new answer will better address your issues. – Richard Smith Dec 16 '17 at 11:26

1 Answers1

1

To remove multiple unwanted arguments in an indeterminate order, you will need to use some form of recursion. Your question contains an example that uses an external redirection loop, but suffers from undesired edge cases.

The edge cases of leaving trailing ? and & can be cleared up using multiple if...return blocks.

For example:

if ($args ~ ^(?:unwanted1|unwanted2)=[^&]*$ ) {
    return 301 $uri;
}
if ($args ~ ^(?:unwanted1|unwanted2)=[^&]*(?:&(.*))?$ ) {
    return 301 $uri?$1;
}
if ($args ~ ^(.*)&(?:unwanted1|unwanted2)=[^&]*(&.*)?$ ) {
    return 301 $uri?$1$2;
}

The above works by treating the two cases when a trailing ? or trailing & occurs, separately with a specially crafted return statement.

The above works by using an external redirection loop.


nginx can also perform internal redirection, and one method to achieve this is to use a rewrite...last from within a location block.

The restriction in this case would be to find the location block which will process the set of URIs that are affected by the unwanted arguments. In the example below, I use the location / block, but your requirements will be affected by the other location blocks within your configuration and the set of URIs affected.

Although you have clearly had success with assigning to the internal $args variable, my answer avoids that technique.

The following example reimplements the previous example using rewrite...last and adds a forth if block to perform the actual return 301.

location / {
    if ($args ~ ^(?:unwanted1|unwanted2)=[^&]*$ ) {
        rewrite ^ $uri? last;
    }
    if ($args ~ ^(?:unwanted1|unwanted2)=[^&]*(?:&(.*))?$ ) {
        rewrite ^ $uri?$1? last;
    }
    if ($args ~ ^(.*)&(?:unwanted1|unwanted2)=[^&]*(&.*)?$ ) {
        rewrite ^ $uri?$1$2? last;
    }
    if ($request_uri ~ \?(.*&)?(unwanted1|unwanted2)= ) {
        return 301 $uri$is_args$args;
    }

    try_files $uri $uri/ =404;
}

Note that the example uses only permitted statements within the if blocks as indicated in this document.

Richard Smith
  • 45,711
  • 6
  • 82
  • 81
  • Thank you for your very detailed answer. I will make thorough tests tomorrow and let you know how it works. – Alex Dec 17 '17 at 16:58
  • Richard - from the server performance point of view I suppose the first technique is preferred while from the SEO and "cleanliness" point of view the second technique is preferred (external redirect chain). Am I correct in assuming this? – Alex Dec 20 '17 at 14:13