7 Nginx rewrite rules with Reg-Ex and Flags examples

The ability to Rewrite an incoming URL to a different URL based on your criteria is an essential feature for any web server.

Nginx Rewrite is very powerful and flexible.

In this article, we will explain the following examples based on Nginx Rewrite:

  1. Example using Nginx Rewrite $ 1, $ 2, ..
  2. Creating a controller file with Nginx Rewrite
  3. Rewrite Break Flag in local context
  4. Adding question mark on line replacement in Nginx Rewrite
  5. If and the Rewrite Directive
  6. Nginx Rewrite Flags Examples
  7. Capturing Nginx Rewrite Access in Error Log File

Following is the syntax for Nginx Rewrite:

rewrite reg-ex replacement [flag];

In the above:

  • The Rewrite directive is part of the ngx_http_rewrite_module.
  • reg-ex – This is the PCRE regex you will specify here. It will be used to match the incoming request to the URI.
  • replacement – If reqeust URI matches REG-ex, then Nginx will use this replacement string to change the request URI
  • flag – will decide whether further Rewrite directives process is required or not. This is explained in detail in one of the examples below.

In Nginx, the Rewrite directive can be specified in one of the following three contexts: server, location, if

1. An example of using Nginx Rewrite $ 1, $ 2, ..

Below is an example of an Nginx Rewrite directive:

rewrite ^(/data/.*)/andreyex/(w+).?.*$ $1/linux/$2.html last;

For example:

  • url / data / distro / andreyex / test.php will be rewritten as url / data / distro / linux / test.html
  • In this example, when you call the original url with test.php from the browser, it will be rewritten based on the above rewrite rule and will point to the test.html page from / data / distro / linux /

In the above rewrite rule:

  • $ 1 and $ 2 will capture the corresponding strings from the original url that do not change
  • The $ 1 in the replacement string will replace what is inside the 1st parenthesis () in reg-exe. In our example, $ 1 in / data /
  • Likewise, $ 2 will replace is within 2 brackets () in reg-exe. So $ 2 in ( w +), so any word that comes after / andreyex / in the original url. In our example, $ 2 is test
  • last – This flag is ensured to stop looking for the Rewrite directive at the current location or block and use the modified URI (i.e. the rewritten URI) and look for a new location for any further Rewrite directives.
  • * $ – Indicates the extension in the original URL. Note that here, the extension from the original URL will be replaced with .html in the URL by Rewrite. This way, even if you call .php on the original url, it will only show the .html file in the rewritten url.

While Nginx rewrite rules do similar things to Apache, there are still many differences in how you write Nginx rewrite rules.

2. Creating a controller file using Nginx Rewrite

Using Rewrite, you can trace many of the original URLs coming in to the controller master template that will serve these requests.

The following Rewrite example explains this.

rewrite ^/linux/(.*)$ /linux.php?distro=$1 last;

In the above example, when you make a request to the URL andreyex.ru/linux/centos, it will get rewritten using the above rule, and it will return a page with this rewritten URL: andreyex.ru/linux.php?distro=centos

As you can see above, any URL that matches the pattern here (i.e. / linux / in the URL) will execute linux.php, but the last part in the original incoming URL will be used as the value for the distro argument of the linux.php controller.

So the above rewrite rule will convert the incoming url like this:

  • linux / centos becomes linux.php? distro = centos
  • linux / debian becomes linux.php? distro = debian
  • linux / redhat becomes linux.php? distro = redhat
  • etc.

As in the previous example, we use $ 1 in the replacement string to capture everything inside the 1st parentheses () in reg-ex. In this case, the last part of the original incoming URL.

We also use the last flag here to instruct Nginx to stop looking for further Rewrite directives in the current-block, and to go to the next match for further searches.

3. Rewrite Break Flag in local context

In this example, we have placed the rewrite condition inside the location directive.

In this example, the location / data / directive also matches $ 1 in the replacement string below.

location /data/ {
 rewrite ^(/data/.*)/andreyex/(w+).?.*$ $1/linux/$2.html break;
 return 403;
}

This is what would happen if you used the last flag:

  • So if you had the last flag after the initial URL rewriting, Nginx will typically look for the next rewrite directive for the new URL.
  • In this case, Nginx will keep redirecting to the same location and continue processing the same rewrite rules a maximum of 10 times, and then it will return a 500 error code.

Since we do not want the behavior described above, we used “break” as a flag that will simply stop block rewriting processing.

4. Adding a question mark when replacing a string in Nginx Rewrite

If the replacement string includes new query arguments, the previous query arguments are appended after them. If you don’t want this, putting a question mark at the end of the replacement string removes the need to add them.

In the following example, the replacement string does not have a question mark at the end. those. no question mark after $ 1

rewrite ^/linux/(.*)$ /linux.php?distro=$1 last;

In the example above, when string replacement includes incoming query arguments, then the arguments from the previous query are appended after them.

A few times, you probably don’t want the addition to happen. What is recommended in this case? Shown below.

In the following example, in the Rewrite Nginx replacement line we added? in the end. There is a question mark after $ 1

rewrite ^/linux/(.*)$ /linux.php?distro=$1? last;

In the example above, the replacement string includes the incoming query arguments, so no arguments from the previous query are added after them.

5. If and the Rewrite Directive

The next few examples show that we can use Rewrite inside an if directive.

You can do if based conditional rewriting if the comparison condition is using variables such as $ scheme, $ http_host, $ http_user_agent, etc. as shown below:

if ($scheme = "http") {
  rewrite ^ https://www.andreyex.ru$uri permanent;
}

if ($http_host = andreyex.ru) {
  rewrite  (.*)  https://www.andreyex.ru$1;
}

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

Note that there are better ways to achieve the end result of the above examples. The above examples are simply given to show that we can add a rewrite directive internally if the statement in the Nginx.

Note that you can also set or disable the following two parameters in the Nginx config file:

server_name_in_redirect on 
port_in_redirect off

6. Examples of flags in Nginx Rewrite

Below are 4 different flags directives in Nginx Rewrite that you can use.

last: This flag will stop processing rewrite directives in the current set, and start at a new location that matches the changed URL.

rewrite ^(/data/.*)/andreyex/(w+).?.*$ $1/linux/$2.html last;

break: This flag will stop processing rewrite directives in the current set.

rewrite ^(/data/.*)/andreyex/(w+).?.*$ $1/linux/$2.html break;

redirect: This flag will do temporary redirects using a 302 HTTP code. This is mainly used when the replacement string is not HTTP or HTTPS, or the $ scheme

permanent: This flag will do a permanent redirect with HTTP 301 code

rewrite ^ https://www.andreyex.ru$uri permanent;

7. Capturing Nginx Rewrite Access in Error Log File

By default, anytime Nginx successfully rewrites it, it doesn’t log it to error.log.

Initially, when you write complex rewrite rules, you really want to make sure that Nginx does the rewrite as per your requirement.

This requires the rewrite log to be enabled, which will add an Nginx entry to the log, making the rewrite successful using any of the rewrite directives in the config file.

To do this, use the rewrite_log directive.

Add the following two lines to your Nginx default.conf:

error_log /var/log/nginx/error.log notice;
rewrite_log on;

In the above:

  • The first line specifies the location of the error_log file where we want the overwrite messages to be logged. Please note that the message is overwritten, such as notification. Thus, you must add “note” at the end of this line as shown above.
  • rewrite_log on – This line enables logging of all directives of the ngx_http_rewrite_module to the error_log file.

After that change, you started seeing lines like these that clearly show which specific rules are being rewritten in the translation of the incoming URL. This will also show the final translation of the URL in the log entry.

[notice] 12345#12345: *1 "^(/data/.*)/andreyex/(w+).?.*$" matches "/data/distro/andreyex/test", client: 192.168.101.1, server: localhost, request: "GET /data/distro/andreyex/test HTTP/1.1", host: "213.159.209.228"
[notice] 12345#12345: *1 rewritten data: "/data/distro/linux/test.html", args: "", client: 192.168.101.1, server: localhost, request: "GET /data/distro/andreyex/test HTTP/1.1", host: "213.159.209.228"

In the above log lines:

  • The first line shows two things 1) Incoming URL 2) Rewrite rules used
  • In the 1st line, the incoming URL (i.e. the request) is shown. In this example, the request is: “GET / data / distro / andreyex / test”
  • In the 1st line, it also shows the Nginx rewrite rules that this incoming request matched. In this example, the rewrite rule used by Nginx is: “^ (/ data /.*)/ andreyex / ( w +) .?. * $”
  • In line 2, shows the rewritten translated URL that was used by Nginx after the rewrite rule was applied. In this example, the translated URL has been rewritten: /data/distro/linux/test.html
Sidebar