How do i rewrite all URL's ending in ?p=1 to the URL without that query in nginx - redirect

I have a website with pagination, which chooses the page to display using the 'p' query.
My issue is that
www.example.com/category.html and
www.example.com/category.html?p=1
Are the same content, and are showing as duplicates for SEO purposes, how do i redirect all ?p=1 queries in nginx to their query free counterpart.
Thanks

The value of the p argument is contained in the $arg_p variable. The if statement can be used to test the value of a variable. The actions available in an if block are limited (see this document for details), but a simple return statement is allowed.
So the simplest solution would be to obliterate the query string from any URI which contains p=1, like this:
server {
...
if ($arg_p = 1) {
return 301 $uri;
}
location / { ... }
}
Note that $uri is the normalised request URI, and is already missing the query string.

Related

nginx: rewrite a LOT (2000+) of urls with parameters

I have to migrate a lot of URLs with params, which look like that:
/somepath/somearticle.html?p1=v1&p2=v2 --> /some-other-path-a
and also the same URL without params:
/somepath/somearticle.html --> /some-other-path-b
The tricky part is that the two destination URLs are totally different pages in the new system, whereas in the old system the params just indicated which tab to open by default.
I tried different rewrite rules, but came to the conclusion that parameters are not considered by nginx rewrites. I found a way using location directives, but having 2000+ location directives just feels wrong.
Does anybody know an elegant way how to get this done? It may be worth noting that beside those 2000+ redirects, I have another 200.000(!) redirects. They already work, because they're rather simple. So what I want to emphasize is that performance should be key!
You cannot match the query string (anything from the ? onwards) in location and rewrite expressions, as it is not part of the normalized URI. See this document for details.
The entire URI is available in the $request_uri parameter. Using $request_uri may be problematic if the parameters are not sent in a consistent order.
To process many URIs, use a map directive, for example:
map $request_uri $redirect {
default 0;
/somepath/somearticle.html?p1=v1&p2=v2 /some-other-path-a;
/somepath/somearticle.html /some-other-path-b;
}
server {
...
if ($redirect) {
return 301 $redirect;
}
...
}
You can also use regular expressions in the map, for example, if the URIs also contain optional unmatched parameters. See this document for more.

nginx redirect old site urls and modify 1 language suffix only

I want to redirect old site urls to new site. But new site has different page names and language chars have changed too.
for example:
en/about/info will redirect to en/com/information
but
ge/about/info will go to ka/com/information
map $request_uri $redirect_uri {
<lang>/about/info/ $lang/com/information/
}
any ideas how I would go about this? There are a lot of urls, so I don't want to write these urls hardcoded for each language.
The map directive can capture parts of a regular expression, but cannot use that capture in the mapped result.
So it is possible to create a named capture called lang (for example) and use it after the mapped variable is evaluated. For example:
map $request_uri $redirect_uri {
~*(?<lang>/\w\w/)about/info/ com/information/;
}
And in the server or location block:
if ($redirect_uri) {
return 301 $lang$redirect_uri;
}
Note that $lang is only created after the value of $redirect_uri is evaluated in the if statement.
See this document for details.

nginx 301 redirect with query string

Currently I have something like this in my nginx.conf file:
location ~ /old/page/?$ {
return 301 /new-page;
}
The issue is that query strings are being stripped from the /old/page?ref=xx URL.
Is it possible to include query strings using the redirect method I'm using above?
Anything from the ? and after is the query string and is not part of the normalised URI used in location and rewrite directives. See this document for details.
If you want to keep the query string, either add it to the return:
location = /old/page/ {
return 301 /new/page$is_args$args;
}
Or with rewrite, the query string is automatically appended unless a ? is added:
rewrite ^/old/page/$ /new/page permanent;
See this document for location syntax, and this document for return/rewrite.

Parameter based redirect in nginx

I have http requests such as the one below being sent to an nginx server:
GET /app/handler?id=1234&param1=cbd&param2=234
Now, I want to rewrite the request to a different handler depending on the id param in the request. eg. redirect to handler_even for even ids and handler_odd for odd ids. This is shown below:
GET /app/handler?id=1234&param1=cbd&param2=234 => /app/handler_even?id=1234&param1=cbd&param2=234
GET /app/handler?id=123&param1=cbd&param2=234 => /app/handler_odd?id=123&param1=cbd&param2=234
I can do the rewrite using proxy_pass, but I'm unsure how to redirect using the id parameter value. Any idea how I could go about this? Would using "if" be the best way to go about this?
Any pointers would be useful
Rather than use an if directive, you could use a map. To internally rewrite the URI use:
map $arg_id $handler {
default /app/handler_even;
~[13579]$ /app/handler_odd;
}
server {
...
location = /app/handler {
rewrite ^ $handler last;
}
...
}
The map should be located at the same level as your server directive (as shown above), i.e. within the http container.
See this document for details.

Nginx redirect URL with specific query parameter

Nginx, I am trying to permanently redirect the URLs with a device GET parameter (http://www.example.org/page?device=desktop) to the relative URL without this parameter (http://www.example.org/page).
I did this, but it doesn't work.
location {
rewrite ^(.*)\?device=desktop $1 permanent;
}
Each query parameter is exposed as a variable prefixed with $arg_ in the configuration file. For example, device would become $arg_device. Using this you can make the comparison check within your location block, for example:
location / {
if ($arg_device = desktop) {
return 301 $uri;
}
}