Site icon GetPageSpeed

NGINX basics. How to create redirects

Adopting NGINX as your web server may be a more challenging task if you come to it after Apache.

One of the primary reasons for that is how different things are in the two webservers. URL redirects are done quite differently in Apache and NGINX.

However, it is quite easy to comprehend how redirects are to be done in NGINX when you know some basics:

In NGINX, you may end up writing redirects with these directives: rewrite, location, return, if, and map. Sounds like too many?
Fear not. There are just a handful of cases to review. Which directives you will use depends on what kind of URLs you are redirecting (whether they use query params), and their number.

Redirecting a single URL irrespective of original arguments

In the simplest case, you want to add a simple redirect from one URL to another, and you don’t bother about the query parameters from the original URL.
The most efficient approach to this would be using the exact matching of the location directive.

To redirect /foo to /bar permanently, you would use:

location = /foo {
    return 301 /bar;
}

What we’ve done there is created an exact location that matches requests for /foo.
A location NGINX is best to be understood as a request’s context.

Exact matching (note equals sign) means that NGINX will match requests to /foo only, and not /foomore.

Throughout request processing, NGINX may “jump” from one context to another, but only a single specific context will be eventually chosen for making up a response.
If a context ends up with a return statement, no more context switching will take place and NGINX will ultimately serve a redirect when either 301 (permanent) or 302 (temporary) status codes are used as the first argument to return.

With our configuration, requests to /foo will be redirected to /bar with the permanent redirect status 301.

Remember, any kind of location matching in NGINX is done against the URI without/irrespective of its arguments.
So the same location will match the URI /foo?bar=1&... or /foo?bar=2&..., etc…
A visitor will be redirected to /bar.

To preserve original URL arguments in the new URL, you will use the $args variable in the new URL:

location = /foo {
    return 301 /bar$is_args$args;
}

Now /foo?bar=1 will be redirected to /bar?bar=1, etc.

When to use exact matching for redirects:

Redirecting many URLs irrespective of their arguments

If you have dozens and dozens of redirects of the previous type, you may want to leverage the map directive.
It comes in handy when you deal with array-like structures in NGINX.

The map directive actually defines a new NGINX variable based on the values of other variables.
For the task of redirecting many URLs, we can simply define a $redirect_to variable based on $uri, and perform a redirect when it isn’t empty.

Remember, the map directive should go directly within http {} context, and not within server {}.

http {

    map $uri $redirect_to {
        default "";
        /foo     /bar;
        /lorem  /ipsum;
        /one    /two;
    }

    # ...
}

Now that we have defined our variable, it can be used in the server block:

server {
    server_name example.com
    if ($redirect_to != "") {
        return 301 $redirect_to;
    }
}

Now, visitors to /foo are redirected to /bar.
Requests to /lorem are redirected to /ipsum.
Requests to /one are redirected to /two.

It’s easy to add many redirects by adding them as new entries under the $redirect_to map.

Using rewrite

The rewrite also helps you in batch redirecting many URLs to many URLs.

If you have clear conformity between the old and new URL sets, you will want to use rewrite for redirects.

Suppose that you had URLs of type /<some.php> using a bunch of PHP files.
Now you have switched to a front-controller CMS framework, where the index.php bootstrap file handles SEO URLs.

For /some.php, you want to redirect to /index.php?page=some. The rewrite comes in very handy because it supports regular expressions:

location / 
    rewrite ^(.*) /index.php?page=$1 permanent;
}

location = /index.php {
   fastcgi_pass ...
}

Note how we have to add prefixed location / and exact located /index.php in order to exclude /index.php itself from the redirect.
When NGINX sees a request for URI /index.php, it will immediately switch to location = /index.php.

The result is:

The rewrite directive requires specifying permanent (permanent redirect) or redirect (temporary redirect) for specifying the type of the desired redirect.

Redirecting a single URL, accounting for its arguments

When you must match the original URL with its arguments, it is easiest to use if and evaluate the value of $request_uri inside it:

if ($request_uri = "/foo?bar=1") {
    return 301 /bar;
}

Redirecting many URLs, accounting for their arguments

Say you had a URL structure that heavily relied on URL parameters, and decided to switch to SEO-friendly URLs. If there is no clear way to define which old URLs correspond to the new URLs, you can use the map approach again.

The only difference to the previous approach is that we are going to use $request_uri variable which includes URL arguments:

http {

    map $request_uri $redirect_to {
        default "";
        "/foo?arg1=val1"  /bar;
        /lorem               /ipsum;
        /one                 /two;
    }

    # ...
}

Now that we have defined our variable, it can be used in the server block:

server {
    server_name example.com
    if ($redirect_to != "") {
        return 301 $redirect_to;
    }
}

Note that /foo will not be redirected, because we now match against the complete URI.
Only visits to /foo?arg1=val1 are redirected to /bar.

Requests to /lorem are redirected to /ipsum.
Requests to /one are redirected to /two.
If parameters are added to those URLs, they will not be redirected.

Permanent redirect from subdirectory to the root

Suppose that you had a multistore Magento and hosted your language-specific stores in subdirectories.
Eventually, you decided to have the single international version of your website at the root, and eliminate the subdirectories setup.
To preserve the SEO juice, create redirects from the subdirectory URLs to the root like this:

rewrite ^/(?:en-sa|ar-sa|en-qa|ar-qa|en-kw|ar-kw|ru-ru|en-ru)/(.*)$ /$1 redirect;

This redirects /en-sa/product.html to /product.html, etc.

Redirects in NGINX are powerful

Web redirects in NGINX are not complicated and can be done in a very efficient manner when you know which case you’re dealing with.

NGINX has the power to map one variable to another, it has regular expression support, different location-matching types, and many built-in variables.

All this requires some learning curve but the result is the rewarding, fast web server operation.

Exit mobile version