<!-- review: finished -->

<a id="http-rewrite"></a>

# Rewrite

The module is used to change request URI using PCRE regular expressions, return redirects, and conditionally select configurations.

The [break](#break), [if](#if), [return](#return), [rewrite](#id4), and [set](#set) directives are processed in the following order:

* the directives of this module specified on the server level are executed sequentially;
* repeatedly:
  > * a location is searched based on a request URI;
  > * the directives of this module specified inside the found location are executed sequentially;
  > * the loop is repeated if a request URI was [rewritten](#id4), but [not more](https://en.angie.software//angie/docs/configuration/modules/http/index.md#internal) than 10 times.

<a id="directives-39"></a>

## Directives

<a id="index-0"></a>

<a id="break"></a>

### break

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `break`;             |
|------------------------------------------------------------------------------------------|----------------------|
| Default                                                                                  | —                    |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | server, location, if |

Stops processing the current set of http_rewrite module directives.

If a directive is specified inside the location, further processing of the request continues in this location.

Example:

```nginx
if ($slow) {
    limit_rate 10k;
    break;
}
```

<a id="index-1"></a>

<a id="if"></a>

### if

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `if` (condition) { ... }   |
|------------------------------------------------------------------------------------------|----------------------------|
| Default                                                                                  | —                          |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | server, location           |

The specified condition is evaluated. If true, this module directives specified inside the braces are executed, and the request is assigned the configuration inside the if directive. Configurations inside the if directives are inherited from the previous configuration level.

#### WARNING
Although directives from other modules can be used inside the if block,
this is not recommended,
as it may lead to unexpected behavior.

A condition may be any of the following:

* a variable name; false if the value of a variable is an empty string or "0";
* comparison of a variable with a string using the "=" and "!=" operators;
* matching of a variable against a regular expression using the "~" (for case-sensitive matching) and "~\*" (for case-insensitive matching) operators. Regular expressions can contain captures that are made available for later reuse in the $1..$9 variables. Negative operators "!~" and "!~\*" are also available. If a regular expression includes the "}" or ";" characters, the whole expressions should be enclosed in single or double quotes.
* checking of a file existence with the "-f" and "!-f" operators;
* checking of a directory existence with the "-d" and "!-d" operators;
* checking of a file, directory, or symbolic link existence with the "-e" and "!-e" operators;
* checking for an executable file with the "-x" and "!-x" operators.

Examples:

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

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

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

if ($slow) {
    limit_rate 10k;
}

if ($invalid_referer) {
    return 403;
}
```

#### NOTE
The value of the [$invalid_referer](https://en.angie.software//angie/docs/configuration/modules/http/http_referer.md#v-invalid-referer) built-in variable is set by the [valid_referers](https://en.angie.software//angie/docs/configuration/modules/http/http_referer.md#valid-referers) directive.

<a id="index-2"></a>

<a id="return"></a>

### return

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `return` code [text];<br/><br/>`return` code URL;<br/><br/>`return` URL;   |
|------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| Default                                                                                  | —                                                                          |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | server, location, if                                                       |

Stops processing and returns the specified `code` to a client. The non-standard code 444 closes a connection without sending a response header.

It is possible to specify either a redirect URL (for codes 301, 302, 303, 307, and 308) or the response body text (for other codes). A response body text and redirect URL can contain variables. As a special case, a redirect URL can be specified as a URI local to this server, in which case the full redirect URL is formed according to the request scheme ($scheme) and the [server_name_in_redirect](https://en.angie.software//angie/docs/configuration/modules/http/index.md#server-name-in-redirect) and [port_in_redirect](https://en.angie.software//angie/docs/configuration/modules/http/index.md#port-in-redirect) directives.

In addition, a URL for temporary redirect with the code 302 can be specified as the sole parameter. Such a parameter should start with the `http://`, `https://`, or "$scheme" string. A URL can contain variables.

See also the [error_page](https://en.angie.software//angie/docs/configuration/modules/http/index.md#error-page) directive.

<a id="index-3"></a>

<a id="id4"></a>

### rewrite

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `rewrite` regex replacement [flag];   |
|------------------------------------------------------------------------------------------|---------------------------------------|
| Default                                                                                  | —                                     |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | server, location, if                  |

If the specified regular expression matches a request URI, URI is changed as specified in the `replacement` string. The rewrite directives are executed sequentially in order of their appearance in the configuration file. It is possible to terminate further processing of the directives using `flags`. If a `replacement` string starts with `http://`, `https://`, or "$scheme", the processing stops and the redirect is returned to a client.

An optional `flag` parameter can be one of:

| `last`      | stops processing the current set of http_rewrite module directives and starts a search for a new location matching the changed URI;     |
|-------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `break`     | stops processing the current set of http_rewrite module directives as with the break directive;                                         |
| `redirect`  | returns a temporary redirect with the 302 code; used if a `replacement` string does not start with `http://`, `https://`, or "$scheme"; |
| `permanent` | returns a permanent redirect with the 301 code.                                                                                         |

The full redirect URL is formed according to the request scheme ($scheme) and the [server_name_in_redirect](https://en.angie.software//angie/docs/configuration/modules/http/index.md#server-name-in-redirect) and [port_in_redirect](https://en.angie.software//angie/docs/configuration/modules/http/index.md#port-in-redirect) directives.

Example:

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

But if these directives are put inside the "/download/" location, the `last` flag should be replaced by `break`, or otherwise Angie will make 10 cycles and return the 500 error:

```nginx
location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
    return  403;
}
```

If a `replacement` string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:

```nginx
rewrite ^/users/(.*)$ /show?user=$1? last;
```

If a regular expression includes the "}" or ";" characters, the whole expressions should be enclosed in single or double quotes.

<a id="index-4"></a>

<a id="rewrite-log"></a>

### rewrite_log

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `rewrite_log` `on` | `off`;   |
|------------------------------------------------------------------------------------------|-------------------------------|
| Default                                                                                  | `rewrite_log off;`            |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | http, server, location, if    |

Enables or disables logging of http_rewrite module directives processing results into the [error_log](https://en.angie.software//angie/docs/configuration/modules/core.md#error-log) at the notice level.

<a id="index-5"></a>

<a id="set"></a>

### set

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `set` $variable value;   |
|------------------------------------------------------------------------------------------|--------------------------|
| Default                                                                                  | —                        |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | server, location, if     |

Sets a value for the specified variable. The value can contain text, variables, and their combination.

<a id="index-6"></a>

<a id="uninitialized-variable-warn"></a>

### uninitialized_variable_warn

| [Syntax](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)   | `uninitialized_variable_warn` `on` | `off`;   |
|------------------------------------------------------------------------------------------|-----------------------------------------------|
| Default                                                                                  | `uninitialized_variable_warn on;`             |
| [Context](https://en.angie.software//angie/docs/configuration/configfile.md#configfile)  | http, server, location, if                    |

Controls whether warnings about uninitialized variables are logged.

<a id="internal-implementation"></a>

## Internal Implementation

The http_rewrite module directives are compiled at the configuration stage into internal instructions that are interpreted during request processing. An interpreter is a simple virtual stack machine.

For example, the directives

```nginx
location /download/ {
    if ($forbidden) {
        return 403;
    }

    if ($slow) {
        limit_rate 10k;
    }

    rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
}
```

will be translated into these instructions:

```console
variable $forbidden
check for zero
    return 403
    end of code
variable $slow
check for zero
match of regular expression
copy "/"
copy $1
copy "/mp3/"
copy $2
copy ".mp3"
end of regular expression
end of code
```

Note that there are no instructions for the [limit_rate](https://en.angie.software//angie/docs/configuration/modules/http/index.md#limit-rate) directive, since it is not related to the `http_rewrite` module. A separate configuration is created for the `if` block. If the condition is true, the request gets this configuration, where `limit_rate` equals 10k.

The directive

```nginx
rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
```

can be made one instruction shorter if the first slash is moved inside the parentheses in the regular expression:

```nginx
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
```

The corresponding instructions will then look like this:

```console
match of regular expression
copy $1
copy "/mp3/"
copy $2
copy ".mp3"
end of regular expression
end of code
```
