Can not use 301 redirect in NGINX - redirect

I have a web site which is translated to 18 languages. Some languages are the same (Brazilian is Portuguese). So I want to redirect from br to pt to avoid odd content, from /some_domain/br/... -> /some_domain/pt/...
I can write single redirect from one domain to another. Something like this:
location = /user/unique {
return 301 http://www.usgreencardoffice.com/blog/the-american-dream;
}
I want to achieve the following:
domain.com/br/something -> domain.com/pt/something
But for the languages redirection, I have no idea. How can I achieve this?

If the language code is at the beginning of the URI, a prefix location will be an efficient solution:
location ^~ /br/ {
rewrite ^/br(.*)$ /pt$1 permanent;
}
The ^~ modifier makes this prefix location take precedence over regex locations at the same level. If you change permanent to last, the rewrite becomes internal and thus invisible to the user.
See this and this for details.

Related

nginx redirect all images to new domain

I had links to my images something like it:
mydomen.com/upload/iblock/f88/f887c7bc3229b93a0a0f7c248d3aefb5.jpg
regex is something like it:
mydomen.com/upload/(catalog|iblock|medialibrary|partners|resize_cache|rk|sale|uf)/*/.(jpg|png|jpeg)
and now i thansfered all my images to storage and now my images have these urls:
images.mydomen.com/iblock/f88/f887c7bc3229b93a0a0f7c248d3aefb5.jpg
so, from mydomen.com i move to images.mydomen.com and removed /upload/
can anyone helps me to redirect all requests images to new domain via nginx location??
You will need to remove the /upload/ prefix from the original URI using a regular expression and capturing the remainder. You can use either the rewrite or location directives.
For example:
rewrite ^/upload((catalog|iblock|medialibrary|partners|resize_cache|rk|sale|uf)/.*\.(jpg|png|jpeg))$ https://images.example.com$1 permanent;
Or using a location block:
location ~* ^/upload((catalog|iblock|medialibrary|partners|resize_cache|rk|sale|uf)/.*\.(jpg|png|jpeg))$ {
return 301 https://images.example.com$1;
}
The regular expression location blocks are evaluated in order, so its position within the configuration file may be significant. See this document for details.

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: 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.