Nginx redirect URL with specific query parameter - redirect

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;
}
}

Related

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.

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

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.

nginx: How to mass permanent redirect from a given list?

I have about 400 url that will change in the new version and for some reasons I can't repeat the same type of url structure in the new website.
My question is, can I give a url list to nginx (yeah I know the 400 ones), and tell him simply that each one of them are going to another url?
Like I said the url structure will be different so I can't use any type of pattern.
Thanks in advance.
The map directive
If you have a very long list of entries, it could be a good idea to keep them outside of the nginx configuration file - using a .map file.
First you need to add a map directive inside your nginx.conf file - keep in mind that your .conf file could be named in another way (e.g. default.conf).
nginx.conf
map_hash_bucket_size 256; # see http://nginx.org/en/docs/hash.html
map $request_uri $new_uri {
include /etc/nginx/oldnew.map; # or any file readable by nginx
}
server {
listen 80;
server_name your_server_name;
if ($new_uri) {
return 301 $new_uri;
}
...
}
Then, the map directive will map any $request_uri to the matching $new_uri found inside the oldnew.map file.
/etc/nginx/oldnew.map:
/my-old-url /my-new-url;
/old.html /new.html;
Be sure to end each line with a ";" char!
Additional configuration
If you need to redirect all URLs to another host, you can use:
return 301 http://example.org$new_uri;
Or, if you also need to redirect to another port, you can use:
return 301 http://example.org:8080$new_uri;
Probably the easiest way to do that is to wrap map directive around your list. The configuration in this case would look like this:
map $request_uri $new_uri {
default "";
/old/page1.html /new/page1.html;
/old/page2.html /new/page2.html;
...
}
server {
...
if ($new_uri != "") {
rewrite ^(.*)$ $new_uri permanent;
}
...
}

how to do nginx rewrites from a url with get parameters

This is my first ever StackOverflow question so please bear with me.
Nginx serves many different sites for us and we have a lot of redirects from migrating clients from different vendors and such. We have set up an /includes directory that houses redirect files for each domain that we migrate over. Occasionally, we will need to write redirects from a url that contains get parameters:
http://example.com/content/default.aspx?NewsId=28
To do this, we have been doing this in an nginx /includes file called example.com-redirects
location ^~ /content/default.aspx {
if ($args ~ "NewsId=28") { rewrite ^ http://example.com/news? permanent; break; }
# add more statements like the one above
}
That has worked just fine for us thus far. Unfortunately, we need to do the same thing but for a different domain that could have the same get parameters. And of course nginx doesn't allow for duplicate locations.
location ^~ /content/default.aspx {
if ($args ~ "NewsId=28") { rewrite ^ http://differentexample.org/news? permanent; break; }
}
I've tried a couple of different solutions all giving me syntax errors. No one at my company is an nginx expert anymore so I could really use some help solving this. I have added an if ($host ~ "example.com") within the location block and that gave me an error. And I've tried adding the location block within the if ($host ~ "example.com") block. Both times nginx told me that I can't put that there.
I usually find my answer in the vast knowledge base that is the internet but seem to be striking out on a solution for this and we're running out of time before we launch this client.
Instead of using if, use a variable. In the virtual host config you set this variable. In the include with the location you use it:
server {
...
set $redirect_host "example.org";
include /includes/news28.conf;
...
}
# include part
location /foo {
if ($args ~ "NewsId=28") { rewrite $scheme://$redirect_host/news? permanent; }
}
Of course you need to set that variable also in the server config of the host already using this include. Hope this helps.

Redirecting and rewriting in NGINX

I'm trying to create a simple "Hello World"-like API and for that I need a rule to redirect/rewrite the URL to my API.
Let's say my file is called index.php, so whenever I make a GET to index.php I get a list of items.
The first thing I want to do is to redirect the URL mydomain.com/index.php to mydomain.com/api.
And second, when mydomain.com/api is accessed, I'd like the server to trigger the index.php file without rewriting the URL.
My current code looks like this:
location /api {
rewrite ^ $scheme://$host/index.php permanent;
}
location /index.php{
return 302 www.mydomain.com/api;
}
but it's not working as expected. Why and how can I fix it?
You need two rules for what you're trying to achieve.
The first one, the one that will receive requests and "translate" them to your under-the-hood script, should look like this:
rewrite ^/api\?(.+)$ /index.php?$1 last;
As for the second one, the one that should redirect all your users to the "beautiful" URL:
rewrite ^/index.php\?(.*)$ /api?$1 permanent;
Note that this second rule should be outside any location block and before any of those, as you're willing to redirect the user before anything else.
Cheers
# you don't need a rewrite. Use location with the "=" or exact match
location = /api {
alias /path/to/root;
index index.php;
}
location /index.php {
return 302 www.mydomain.com/api;
}
Hope it helps
Here is the second version of my answer using one redirect and an alias:
location /api {
alias /path/to/root;
index index.php;
}
# replace index.php with api
location /index.php {
rewrite (index\.php)(.*)$ /api$2 permanent;
}
My first solution did not forwarded the args. Reading #alexandernst solution gave a better idea of the problem.