Nginx Rewriting and Returning

nginx(8) allows for requests to be (conditionally) rewritten and returned.


Logical Control

The if directive allows for rewrite and return directives to be applied conditionally.

A condition can be any of:

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:

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


CategoryRicottone

Nginx/RewritingAndReturning (last edited 2023-04-24 18:39:01 by DominicRicottone)