NGINX rewrite and return rules are used to change the URL requested.
The are many reasons to change totally or in part the URL requested, common examples are
keeping url clean removing the extension (blogs), redirect content from a domain to another.
The are two main directives to do such job: return and rewrite.
Both the directives perform the same function, but the rewrite
directive can do parsing of the url and thus is more flexible and customizable than the return
directive.
we will be using the same piece of configuration chaging only code in the commented part.
server {
listen 80;
server_name example.com;
root /var/www/default/;
error_log /var/log/nginx/example_error.log error;
access_log /var/log/nginx/example_access.log combined;
#--- BEGIN DIRECTIVES ---#
#--- END DIRECTIVES ---#
error_page 404 /404.html;
}
Return
Syntax: return code [text];
return code URL;
return URL;
Default: β
Context: server, location, if
Return stops processing and returns the specified code to a client, so no further operations will be perfomerd by the server. Notice the the context can be either server or location.
There area 3 possibile ways to use the return keyword:
- return a status code an a message test (es. 404 NOT FOUND)
- return a status code and a URL to be redirected to (301 http://newsite.dev)
- return a URL to be redirected to
Return Redirect
$sheme
is the protolo (http|https) while $request_uri
is the resource requested on the server
return 301 $scheme://www.newsite.com$request_uri;
This will redirect for example from http://example.com/admin.html to http://www.newsite.com/admin.html sending the status code 301
(Moved Permanently), obiviously you can redirect only the $requested_uri
to a fixed one.
Sending a permanent redirect
code 301 makes the browser forget the original address entirely and prevents it from attempting to access that address anymore.
It is possible to specify a redirect URL
for different codes such as 301, 302, 303, 307 or a response body text
for codes such as 1xx, 2xx, 4xx, 5xx.
Other examples:
return 401 "Access denied";
return 404 "Try Later, I'm not here";
return 403 "Service unavailable"
Dropping Requests for unwanted extensions
if URL location contains one of the listed extensions Nginx returns tha status code 410 (Gone) that indicates that the resource is permantently unavailable.
location ~ .(aspx|asp|jsp|cgi)$ {
return 410 "no no no";
}
Rewrite
Syntax: rewrite regex replacement [flag];
Default: β
Context: server, location, if
The rewrite directive is a little more complex.
The syntax is:
rewrite regex replacement [flag];
where regex
is a regualar expression matched againt the requested URI, the replacement
part indicates what to change in the requested URI, and the flag
is use to perform more processings in the rewrite or stops. In fact if a new rewritten url mathches another rewrite directive you can choose to proced with the rewrite of the URI or not using the flag.
Flag can be
- last
- stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI;
- break
- stops processing the current set of ngx_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.
A rewrite directive will only return an HTTP 301 or 302 status code, if you need to return a differente status code an explicit return directive must be inserted after the rewrite directive.
Get File
Suppose to have media files organized in subfolders such as /media/mp3 or /media/pdf. We can access simply rewriting the url and indicating the name og the file in this way
http://exameple/mp3/zappa
or http://exameple/pdf/catalog
but in reality the files will be found in /media/mp3/zappa.mp3 or /media/pdf/catalog.pdf
rewrite ^/(.*)/(.*)$ /media/$1/$2.$1 last;
The first (.*) is matched with mp3 and the second with zappa and would be assigned to $1 and $2 variables and used in replacement url.
Clean URLs
Remove the .html
extensions from the url making the URL more readable.
rewrite ^(/.*)\.html(\?.*)?$ $1$2 redirect;
rewrite ^/(.*)/$ /$1 redirect;
location / {
try_files $uri/index.html $uri.html $uri/ $uri =404;
}
The try_files
directive indicates to the server to check for the existence of index.html file inside $uri directory , then for a $uri.html file, then directory $uri/ and finally for a file named $uri.
If nothing is found, Nginx returns a status 404.
Rewrite dynamic URLs
Suppose to have a url like this http://example.com/profile.html?userid=32
and we want to rewrite to something more readable, somthing like http://example.com/profile/32
.
rewrite ^/profile/(.*)$ /profile.html?userid=$1 last;
Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
Add WWW to domain
if ( $host !~ ^www\. ) {
return 301 $scheme://www.$host$request_uri;
}