Nginx Rewriting and Returning
nginx(8) allows for requests to be (conditionally) rewritten and returned.
Contents
Logical Control
The if directive allows for rewrite and return directives to be applied conditionally.
A condition can be any of:
A variable name, which evaluates as false if the value is an empty string or "0".
A (literal or variable) comparison using the = and != operators.
- Note that all values are strings, so quoting is optional.
Regular expression matching using the ~ and ~* operators. (The former is case sensistive, the latter is case insensitive.)
Regular expressions can contain capture groups, which then store the captured value in $1 through $9.
Negate a match by prefixing the operator with !; for example !~ and !~*.
If a regular expression includes } or ;, it must be quoted.
File existence with the -f and !-f operators.
Directory existence with the -d and !-d operators.
File/directory/symlink existence with the -e and !-e operators.
Executable file existence the -x and !-x operators.
A variable can be declared with the set directive. The variable name should be prefixed with $.
The break directive causes a request to skip all remaining rewrite, return, and logical control directives.
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } if ($slow) { limit_rate 10k; break; } if ($request_method = POST) { return 405; }
Rewrite
The rewrite directive takes a regular expression, a replacement string (which can use variables), and an option.
The regular expressions here follow the same rules as above. Notably:
Regular expressions can contain capture groups, which then store the captured value in $1 through $9.
If a regular expression includes } or ;, it must be quoted.
If a replacement string starts with http://, https://, or $scheme, this is treated as a permanent redirect and immediately returns.
The valid options are:
Option |
Meaning |
last |
Re-scan for locations using the rewritten URI |
break |
Skip all remaining rewrite, return, and logical control directives |
redirect |
Returns a redirect with a 302 code |
permanent |
Returns a permanent redirect with a 301 code |
Removing Path Components
To rewrite a URI, try:
server { rewrite ^/example(.*)$ $1 last; }
The last option should be replaced with break when used within a location. Otherwise nginx(8) will repeatedly re-enter the location and, after 10 cycles, return an error.
location /example { rewrite ^/example(.*)$ $1 break; }
Removing Arguments
If a replacement string includes the new request arguments, the old arguments are appended.
To avoid this, append a ? to the replacement string
rewrite ^/users/(.*)$ /show?user=$1? last;
Return
The return directive takes a code and optionally a URI.
Returning Plain Text
It is also possible to return a literal text message.
location / { add_header Content-Type text/plain; return 200 'hello, world!'; }
Variables can be used in the text.
Redirecting Requests
To redirect a request, use a 30x code and a new URI.
server { listen 80; server_name old.example.com; return 301 $scheme://new.example.com$request_uri; }
Rejecting Requests
To reject a request, the nginx(8) convention is to return the non-standard error code 444.
This is often done within a location mapping to a sensitive directory or file
location ~ ^\.ht { return 444; }
But it can also be used with the if directive shown above.
if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }
See also
Module ngx_http_rewrite_module documentation