= 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 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 [[Nginx/Location|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 [[Nginx/Location|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 == [[https://nginx.org/en/docs/http/ngx_http_rewrite_module.html|Module ngx_http_rewrite_module documentation]] ---- CategoryRicottone