NGINX Redirect or Alias? - nginx

I want to do a redirect in order to give a cleaner url for my users.
I want to change:
http://mydomain.com/main/username/profile
To:
http://mydomain.com/username/profile
Would I do this with a rewrite or an alian and how?

First you have to understand what the difference between a redirect and an alias is.
Redirect
A redirect will send a user who requests /main/username/profile to /username/profile. The URL will change in the browser. This is particularly important if the URL is accessible by search engines, because they would otherwise index the same page twice (duplicated content).
If you decide to use a redirect you should be sure, that your URLs stay that way. The reason for this is Cool URIs don't change.
Example for a redirect:
server {
# ...
location / {
# ...
location ~ /main/([a-zA-Z0-9]+)/profile$ {
# SEO effective redirect
return 301 /$1/profile;
}
# ...
}
}
nginx documentation: return
nginx wiki: return
Alias
An alias is used to tell nginx that that a requested file is not mapped by the URL on the filesystem and that it should have a look elsewhere. The following example is from the nginx wiki:
root /var/www;
location /i/ {
alias /spool/w3/images/;
}
A request for /i/empty.gif will not map to /var/www/i/empty.gif. Instead it will be matched to /spool/w3/images/empty.gif.
nginx documentation: alias
nginx wiki: alias

Related

NGINX Redirect All Requests Matching URL with Parameters to Subdomain

I have a website that is also serving api requests to an app on the main domain. I would like to send all matching /api requests to an api subdomain.
For example I would like https://example.com/api + https://example.com/api/some_action + https://example.com/api/some_action?params1=somevalue&params2=value2.... to redirect to the same url structure but just on the subdomain.
So for the above example:
https://example.com/api
-> https://api.example.com/api
https://example.com/api/some_action
-> https://api.example.com/api/some_action
https://example.com/api/some_action?params1=somevalue&params2=value2....
-> https://api.example.com/api/some_action?params1=somevalue&params2=value2....
For all types of requests (get, posts etc) as well. So far I have tried this in the server directive for the main domain (in the 443 SSL server directive)
location ~ /api(.*)$ {
return 301 https://api.example.com/api/$request_uri$is_args$args;
}
The result I get when performing a simple GET request on https://api.example.com/api/some_action?param1=value ... is https://api.example.com//some_action without parameters and missing the api.
To redirect example.com/api/foo?bar to api.example.com/api/foo?bar you should use:
location ^~ /api {
return 307 https://api.exemple.com$request_uri;
}
The $request_uri variable contains the original request, including the /api/ prefix and the query sring.
The ^~ operator gives this location precedence (see this document for details). The 307 status code maintains GET/POST through the redirection (see this link for more).

How can I redirect users with custom request (not folder) to root folder?

I need to redirect a facebook ID link (https://example.com/?fbclid=some_gibberish_text) to my root folder. I am using return 301 but gotten no result. Below is my configuration in nginx.conf:
location ^~ /?fbclid=(.*) {
return 301 https://example.com;
}
I am kind of new to Nginx. How do I achieve this?
Thanks.
Request parameters are not subject to match in location blocks. The matching is performed against a normalized URI without the arguments (?arg1=value1&arg2=value2...) part. With your example, you are trying to redirect a request from the root folder to the same root folder. Depending on what you really need, you can redirect any request containing fbclid argument to the root of your site:
if ($arg_fbclid) {
return 301 https://example.com;
}
or, if you want to hide this argument from your backend, just get rid of it:
if ($args ~ (.*)(^|&)fbclid=[^&]*(\2|$)&?(.*)) {
set $args $1$3$4;
}
(this complex regex removes the corresponding request argument whether it is at the beginning, in the middle or at the end of the request string).
Put one of these constructions outside your location blocks.

Rewrite Nginx URLs with Parameters (After a Question Mark)

I have URLS in this format:
/wiki/index.php?title=Widget
/wiki/index.php?title=Blue
/wiki/index.php?title=Red
/wiki/index.php?title=Etc
I want to be able to match any URL that has the pattern "/wiki/index.php?title=" or even just "/wiki/index.php" (but so it will pick up the above URLs with the "?") and then redirect them to simply /wiki/ (all pages that match the above pattern go to the single url /wiki/)
I used to have a Mediawiki install on the /wiki/ directory with a lot of pages in the format above. However now I am running a Wordpress install and it is using the /wiki/ directory. I don't need each rewritten URL to go to a different URL (I know that is difficult as my source URLs have parameters) but right now they all 404 and so I just want to direct to them /wiki/ at least.
Simple URL rewriting
The easiest case (rewrite all /wiki/index.php requests with any arguments) can be done by this config (inside your server block):
location = /wiki/index.php {
rewrite .* /wiki/?;
}
The '?' sign at the end of second rewrite parameter is a trick to completely remove any request arguments. Without it, request /wiki/index.php?title=Widget will be rewrited to /wiki/?title=Widget.
Rewriting only requests matching /wiki/index.php?title=... is a more complex, I don't know how to do it without if construction:
location = /wiki/index.php {
if ($request_uri ~ ^/wiki/index\.php\?title=) {
rewrite .* /wiki/?;
}
}
If you want to generate HTTP 301 or 302 redirect instead of simple URL rewriting, you can use redirect (for 301 temporary redirect) or permanent (for 302 permanent redirect) flag at the end of rewrite directive parameters (see documentation).
Rewriting URLs to individual pages
This task is not as difficult as it seems. For redirecting /wiki/index.php?title=Widget to /wiki/Widget, /wiki/index.php?title=Blue to /wiki/Blue etc. we can make use of map directive:
map $request_uri $uri_suffix {
~^/wiki/index\.php\?title=([^&]*) $1;
}
server {
...
location = /wiki/index.php {
rewrite .* /wiki/$uri_suffix?;
}
...
}
Please note that map directive must be declared outside your server configuration block!

NGINX location block always redirect to different location

I have NGINX hosting many drop in apps that will usually all use the same api. My nginx has a location block for that api, so something liek
location /default-api/ {
proxy_pass https://some/location.com;
}
Usually each GUI will want to use the same api, occasionally someone may wish to change the api a specific app uses though. I wanted each GUI to be configured to hit a different url, so that it's easier to redirect that url later if someone wants to change their api, but rather then hard coding each url to https://some/location.com in each location block I wanted to redirect to the default-api.
So effectively I want something like, if it would work
location /foo-api/ {
redirect /default-api/;
}
location /bar-api/ {
redirect /default-api/;
}
location /baz-api/ {
redirect /default-api/;
}
I thought when I first played with nginx that I saw a very simple directive for doing this, but I can't find it now. I know a number of directives could do this, but none of the ones I know of feel clean enough to be worth doing.
rewrite requires an overly complex regex, redirect requires the client to make a new query after getting the redirect. proxy_pass does some unneeded proxying logic, all three seem to require me to hardcode the servername into the redirect path. the cleanest I could figure out was possibly using tryfiles in a manner it wasn't made for.
Is there some simpler directive to do an internal redirect like this?
Two suggestions.
1) Comment out the location /foo-api block unless it is needed:
location / {
rewrite ... ... break; # if required to normalize the /prefix/...
proxy_pass ...;
}
# location / foo-api/ { } # disabled - use `location /`
2) Use a named location:
location /default-api/ {
try_files /nonexistent #api;
}
location /foo-api/ {
try_files /nonexistent #api;
}
location #api {
rewrite ... ... break; # if required to normalize the /prefix/...
proxy_pass https://some/location.com;
}

nginx substitude file sitemap.xml on subdomain

I have file sitemap.xml in site public directory. When I use subdomain 'm.', it uses same public directory as general site. I need to return file '/mobile-sitemap.xml' from url '/sitemap.xml', when I'm on subdomain 'm.'.
What nginx modules and rules could help me to do this?
My first step was like this:
if ($host ~* m\.(.*)) {
#if url = /sitemap.xml, give back file /mobile-sitemap.xml as /sitemap.xml
}
Or maybe it's ok to google, if i just send 301 redirect to another sitemap file?
You could create a separate server block for your mobile subdomain, in which case the if statement would not be necessary. See this caution on the use of if.
However, to implement this in a single server block, use a location and a rewrite:
location = /sitemap.xml {
if ($host ~* m\.) {
rewrite ^ /mobile-sitemap.xml last;
}
}
See this and this for more.

Resources