Darmikon
3/3/2015 - 12:47 PM

NGINX Redirect, Rewrite

NGINX Redirect, Rewrite

Redirect: Rewrite vs Return

Source

More often than not there are times when your initial thought process changes mid way through your production ready application and you decide to change your application url. It could be your scheme (from a non-www to a www or vice-versa) or it could be your protocol (say, from http to https).

There are two ways of implementing this change in nginx.

Redirect from non-www to www

server {
        server_name example.com;
        # Option 1
        return 301 $scheme://$host$request_uri;

        # Option 2
        rewrite ^ http://$host$request_uri? permanent;
}

Redirect from http to https

server {
        server_name example.com;
        # Option 1
        return 301 https://$server_name$request_uri;

        # Option 2
        rewrite ^ https://$server_name$request_uri? permanent;
}

REWRITE

  • Only the part of the original url that matches the regex is rewritten.
  • Slower than a Return.
  • Returns HTTP 302 (Moved Temporarily) in all cases, irrespective of permanent.
  • Suitable for temporary url changes.

RETURN

  • The entire url is rewritten to the url specified.
  • Faster response than rewrite.
  • Returns HTTP 301 (Moved Permanently).
  • Suitable for permanent changes to the url.
  • No need to set permanent.
  • More details on nginx can be found here

Efficient 301 Redirects

Source

Traditionally, web sites use either www or non-www version to display their content to the visitors. Sub-domains are also becoming popular in recent times. When www is chosen as the preferred domain when installing WordPress (or after installing WordPress), whenever a visitor types non-www version of the site, WordPress redirects the visitor to the correct URL, the www version the site, through an internal 301 redirect. Google recommends this 301 redirect and Google WebMaster Tools has an option to set the preferred domain too.

In performance optimization, every tiny improvement helps to speed up and scale up the site. When 301 redirect is done by WordPress, it requires PHP to be processed. When 301 redirect is done at the server level, without using PHP, the process is more efficient, so requires less time to execute.

Let’s see how newbie webmasters traditionally set up 301 redirects in Nginx…

Nginx 301 redirect (non-www to www – traditional way)

server {
    server_name domainname.com;
    rewrite ^/(.*)$ http://www.domain.com/$1 permanent;
}

Nginx 301 redirect (www to non-www – traditional way)

server {
    server_name www.domainname.com;
    rewrite ^/(.*)$ http://domain.com/$1 permanent;
}

As already mentioned, above methods are done at the server level that is more efficient than doing at the application level (read application = WordPress) and every bit of improvements helps. So, let’s break the tradition and see how we could achieve the same in a more efficient way, using Nginx.

For the following examples that use Nginx, no extra modules needed to make them work. The return directive is part of the standard Rewrite module in Nginx.

Nginx 301 redirect (non-www to www – new, efficient, & the best way)

server {
    server_name domainname.com;
    return 301 $scheme://www.domainname.com$request_uri;
}

Nginx 301 redirect (www to non-www – new, efficient, & the best way)

server {
    server_name www.domainname.com;
    return 301 $scheme://domainname.com$request_uri;
}

In the above examples, by using Redirect directive of Apache and return directive of Nginx, we can effectively avoid doing any capturing or matching at all and thus we can completely avoid evaluation of a regular expression.

Nginx no-www to www and www to no-www

Source

Actually you don't even need a rewrite.

server {
    #listen 80 is default
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    #listen 80 is default
    server_name example.com;
    ## here goes the rest of your conf...
}

As my answer is getting more and more up votes but the above as well. You should never use a rewrite in this context. Why? Because nginx has to process and start a search. If you use return (which should be available in any nginx version) it directly stops execution. This is preferred in any context.

Redirect both, non-SSL and SSL to their non-www counterpart:

server {
    listen 80;
    listen 443 ssl;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    listen 80;
    listen 443 ssl;
    server_name example.com;
    # rest goes here...
}
~~~

The $scheme variable will only contain http if your server is only listening on port 80 (default) and the listen option does not contain the ssl keyword. Not using the variable will not gain you any performance.

**Redirect everything to SSL (personal config on UNIX with IPv4, IPv6, SPDY, ...):**

```text
#
# Redirect all www to non-www
#
server {
    server_name          www.example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:80;
    listen               *:443 ssl spdy;
    listen               [::]:80 ipv6only=on;
    listen               [::]:443 ssl spdy ipv6only=on;

    return 301 https://example.com$request_uri;
}

#
# Redirect all non-encrypted to encrypted
#
server {
    server_name          example.com;
    listen               *:80;
    listen               [::]:80;

    return 301 https://example.com$request_uri;
}

#
# There we go!
#
server {
    server_name          example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:443 ssl spdy;
    listen               [::]:443 ssl spdy;

    # rest goes here...
}

I guess you can imagine other compounds with this pattern now by yourself.

More of my configs? Go here and here.

Nginx no-www to www and www to no-www

Source

HTTP Solution

From the documentation, "the right way is to define a separate server for example.org":

server {
    listen       80;
    server_name  example.org;
    return       301 http://www.example.org$request_uri;
}

server {
    listen       80;
    server_name  www.example.org;
    ...
}

HTTPS Solution

For those who want a solution including https://...

server {
        listen 80;
        server_name www.domain.com;
        // $scheme will get the http protocol
        // and 301 is best practice for tablet, phone, desktop and seo
        return 301 $scheme://domain.com$request_uri;
}

server {
        listen 80;
        server_name domain.com;
        // here goes the rest of your config file
        // example 
        location / {

            rewrite ^/cp/login?$ /cp/login.php last;
            // etc etc...

        }
}

Note: I have not originally included https:// in my solution since we use loadbalancers and our https:// server is a high-traffic SSL payment server: we do not mix https:// and http://.

To check the nginx version, use nginx -v. Here is a solution for older nginx versions...

Strip www from url with nginx redirect

server {
    server_name  www.domain.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}

server {
    server_name  domain.com;
    #The rest of your configuration goes here#
}

So you need to have TWO server codes.

Add the www to the url with nginx redirect

If what you need is the opposite, to redirect from domain.com to www.domain.com, you can use this:

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    server_name  www.domain.com;
    #The rest of your configuration goes here#
}

As you can imagine, this is just the opposite and works the same way the first example. This way, you don't get SEO marks down, as it is complete perm redirect and move. The no WWW is forced and the directory shown!

Some of my code shown below for a better view:

server {
    server_name  www.google.com;
    rewrite ^(.*) http://google.com$1 permanent;
}

server {
       listen 80;
       server_name google.com;
       index index.php index.html;
       ####
       # now pull the site from one directory #
       root /var/www/www.google.com/web;
       # done #
       location = /favicon.ico {
                log_not_found off;
                access_log off;
       }
}

Redirect: Temporary and Permanent

Source

What is an HTTP Redirect?

HTTP redirection, or URL redirection, is a technique of pointing one domain or address to another. There are many uses for redirection, and a few different kinds of redirection to consider.

As you create content and administrate servers, you will often find the need to redirect traffic from one place to another. This guide will discuss the different use-cases for these techniques, and how to accomplish them in Apache and Nginx.

Why Do Servers Use Redirects?

Redirects are used whenever a site needs people requesting one address to be directed to another address. There are many situations where you may find yourself in this position.

Moving to a Different Domain

If you have established a web presence and would like to change your domain, it is best not to just abandon your old domain.

Bookmarks to your site and links to your site located on other pages throughout the internet will break if your content disappears without any instructions to the browser about how to find its new location.

Changing domains without redirecting will cause your site to lose traffic from previous visitors and lose all of the credibility you have worked to establish.

Expanding to Capture Similar Domains

Often, it is helpful to register multiple variations of a name in order to benefit from users typing in addresses similar to your main domain.

For example, if you have a domain called "mymessyspiders.com", you might also buy the domain names for "mymessyspiders.net" and "mymessyspiders.org" and redirect them both to your "mymessyspiders.com" site.

This allows you to catch users who might be trying to get to your site with the wrong address. It can also help prevent another site from using a similar domain and profitting off of your web presence.

Creating a Persistant Experience In Spite of Page Name Changes

Sometimes, it is necessary to change the names of pages that have already been published and received traffic on your site.

Normally, this would lead to a 404 Not Found error or possibly another error depending on your security settings. These can be avoided by leading your visitors to another page that contains the correct content they were trying to access.

Forcing SSL

A simple but common use for redirects is directing all site traffic to use SSL instead of standard HTTP.

Using redirects, it is possible to make all requests for "http://www.mysite.com" be redirected to "https://www.mysite.com".

Note the HTTPS instead of HTTP.

Redirect Methods

There are a few different kinds of URL redirects, each of which mean something different to the client browser.

The two most common types are 302 temporary redirects, and 301 permanent redirects.

Temporary Redirects

Temporary redirects are useful if your web content for a certain URL temporarily needs to be served out of a different location.

For example, if you are performing site maintenance, you may wish to use a temporary redirect of all of the pages for your domain to an explanation page to inform your visitors that you will be back shortly.

Temporary redirects inform that browser that the content is temporarily located at a different location, but that they should continue to attempt to access the original URL.

Permanent Redirects

Permanent redirects are useful when your content has been moved to a new location forever.

This is useful for when you need to change domains or when the URL needs to change for other reasons and the old location will no longer be used.

This redirect informs the browser that it should no longer request the old URL and should update its information to point to the new URL.

How to Redirect in Nginx

Redirects in Nginx are in many ways much simpler to accomplish. Most of the times, you can redirect by creating a server block for the content you would like to redirect.

For example, if you would like to redirect requests for "domain1.com" to "domain2.com", you could create a server block that looks like this:

server {
    listen 80;
    server_name domain1.com;
    return 301 $scheme://domain2.com$request_uri;
}

The "return" directive executes a URL substitution and then returns the status code given to it and the redirection URL.

In this case, it uses the "$scheme" variable to use whatever scheme was used in the original request (http or https). It then returns the 301 permanent redirect code and the newly formed URL.

In order to process a folder redirect to a separate subdomain, we can perform an operation similar to the Apache folder redirection using the "rewrite" directive:

rewrite ^/images/(.*)$ http://images.example.com/$1 redirect;

This directive, when placed in a server block, will issue a temporary redirect for requests inside the "images" directory to the subdomain "images.example.com".

For a permanent redirect, you could change "redirect" to "permanent" at the end of the statement.