NGINX Rewrite Rules

nginx rewrite

The two main directives used to rewrite in Nginx are the return and rewrite directives, both of which will be explained in this article. Nginx rewrite rules can be defined within your Nginx configuration file in order to change at least part or all of a URL. Usually, this is done for one of two purposes.

  • First, if a URL has changed, using a rewrite rule will let the client know that the resource requested is in a different location. Additionally, if the client makes a common misspelling of the domain name, return and rewrite directives can also be used to help rectify this issue and point the client to the correct URL.
  • Second, rewrite rules can also be used to control the request within Nginx. For example, a request can be forwarded to an application if the content will be generated dynamically.

The Nginx return Directive Explained

The Nginx return directive is the simpler directive to use compared to Nginx rewrite. To use the return directive, it must be enclosed within a server or location block which defines which URLs should be rewritten. The directive should then define the rule which will rewrite the requested URL and return the correct URL.

An example of the return directive being used within a server block may look similar to the following:

server {
 listen 80;
 server_name www.old-website.com;
 return 301 $scheme://www.new-website.com$request_uri;
}

In the above example, the old website address would correspond to the client requested URL. The return directive would then return a 301 status code to the browser and redirect the client to the new website address. the Nginx variable $scheme is used to define the protocol (http or https) while $request_uri is for the full URI.

The Nginx rewrite Directive Explained

Similar to the return directive, the Nginx rewrite directive needs to be in a location or server block in order to rewrite the URL. Other than that similarity, both directives are rather different from one another. This directive can be used to perform more granular tasks as with it you can perform more complicated URL distinctions such as:

  • Capture elements in the original URL
  • Change or add elements in the path

The Nginx rewrite directive is in some cases more complicated. The basic syntax looks like this:

rewrite regex URL [flag];

The Nginx rewrite directive does not send a redirect to the client in all cases. If the rewritten URL matches with another following directive, Nginx will rewrite the URL again. A rewrite directive will only return a HTTP 301 or 302 status code. If another status code is required, a return directive is needed after the rewrite directive. For an example of a rewrite directive being used in conjunction with the return directive let’s take a look at an example from Nginx’s rewrite module documentation.

server {
 ...
 rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
 rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
 return 403;
 ...
}

In the above scenario, all URLs that begin with /download and then later include /media or /audio are matched. It then replaces the /media or /audio elements with /mp3 and adds the .mp3 or .ra file extension. The return directive specifies that if the URL does not match the rewrite rules then return a 403 back to the client.

For some additional Nginx rewrite/return examples, take a look through the following cases.

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}

if ($request_method = POST) {
    return 405;
}

if ($invalid_referer) {
    return 403;
}

Helpful Nginx Variables

You’ve likely noticed a few reoccurring variables in the rewrite examples above. These variables come predefined in Nginx although there are many more than what is just listed below, the following is a short list of frequently used variables.

  • $request_method – Defines the request method (e.g. GET or POST)
  • $scheme – Defines the request scheme (e.g. http or https)
  • $request_uri – Defines the full original request URI (including arguments)
  • $args – Defines the arguments in the request line
  • $server_name – Defines the name of the server which accepted the request

Converting Apache Rewrite Rules to Nginx

If you’re using Apache as your web server but want to make the switch to Nginx, the process can be cumbersome depending upon how many rules you have defined. Learning how to rewrite these rules can take some time to get used to. Nginx provides a few examples of rewrite rule conversions from Apache to Nginx. Take for example the following rewrite rule in Apache:

RewriteCond %{HTTP_HOST} example.com
RewriteRule (.*) http://www.example.com$1

When converting this to Nginx, it’s best to split these rules into two separate server blocks in order to make things as efficient as possible. For example:

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

server {
    listen 80;
    server_name www.example.com;
    # ...
}

Knowing how to convert Apache rules to Nginx properly does take time and experience. If you want to expedite the process, check out this htaccess to nginx converter.

htaccess nginx converter

That being said, don’t assume that all conversion rules will be optimized for performance or even 100% correct. You’ll need to at least have a basic understanding of converting these rules and they should always be double-checked when using an automated tool.

Summary

Having the ability to rewrite URLs in Nginx is an extremely powerful feature. Rewrite rules can go much further than simply redirecting a simple URL from its http version to its https version. However, learning how to properly implement these rules can take some time and requires some knowledge. To learn more about Nginx rewrite rules, check out this guide by Nginx themselves which provides various examples of the best ways to go about rewriting URLs in your Nginx configuration.