Nginx Rewrite Rules
The two main directives used to rewrite in Nginx are the return and rewrite directives, both of which will be explained in this article. Nginx rewrite rules can be defined within your Nginx configuration file in order to change at least part or all of a URL. Usually, this is done for one of two purposes.
- First, if a URL has changed, using a rewrite rule will let the client know that the resource requested is in a different location. Additionally, if the client makes a common misspelling of the domain name, return and rewrite directives can also be used to help rectify this issue and point the client to the correct URL.
- Second, rewrite rules can also be used to control the request within Nginx. For example, a request can be forwarded to an application if the content will be generated dynamically.
The Nginx return
directive explained
The Nginx return
directive is the simpler directive to use compared to Nginx rewrite. To use the return directive, it must be enclosed within a server or location block which defines which URLs should be rewritten. The directive should then define the rule which will rewrite the requested URL and return the correct URL.
An example of the return directive being used within a server block may look similar to the following:
server {
listen 80;
server_name www.old-website.com;
return 301 $scheme://www.new-website.com$request_uri;
}
In the above example, the old website address would correspond to the client requested URL. The return directive would then return a 301
status code to the browser and redirect the client to the new website address. the Nginx variable $scheme
is used to define the protocol (http
or https
) while $request_uri
is for the full URI.
The Nginx rewrite
directive explained
Similar to the return
directive, the Nginx rewrite
directive needs to be in a location
or server
block in order to rewrite the URL. Other than that similarity, both directives are rather different from one another. This directive can be used to perform more granular tasks as with it you can perform more complicated URL distinctions such as:
- Capture elements in the original URL
- Change or add elements in the path
The Nginx rewrite
directive is in some cases more complicated. The basic syntax looks like this:
rewrite regex URL [flag];
The Nginx rewrite
directive does not send a redirect to the client in all cases. If the rewritten URL matches with another following directive, Nginx will rewrite the URL again. A rewrite
directive will only return an HTTP 301
or 302
status code. If another status code is required, a return
directive is needed after the rewrite
directive. For an example of a rewrite directive being used in conjunction with the return directive let's take a look at an example from Nginx's rewrite module documentation.
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
In the above scenario, all URLs that begin with /download
and then later include /media
or /audio
are matched. It then replaces the /media
or /audio
elements with /mp3
and adds the .mp3
or .ra
file extension. The return directive specifies that if the URL does not match the rewrite rules then return a 403
back to the client.
For some additional Nginx rewrite/return examples, take a look through the following cases.
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}
if ($invalid_referer) {
return 403;
}
Helpful Nginx variables
You've likely noticed a few reoccurring variables in the rewrite examples above. These variables come predefined in Nginx although there are many more than what is just listed below, the following is a short list of frequently used variables.
$request_method
- Defines the request method (e.g.GET
orPOST
)$scheme
- Defines the request scheme (e.g.http
orhttps
)$request_uri
- Defines the full original request URI (including arguments)$args
- Defines the arguments in the request line$server_name
- Defines the name of the server which accepted the request
Converting Apache rewrite rules to Nginx
If you're using Apache as your web server but want to make the switch to Nginx, the process can be cumbersome depending upon how many rules you have defined. Learning how to rewrite these rules can take some time to get used to. Nginx provides a few examples of rewrite rule conversions from Apache to Nginx. Take for example the following rewrite rule in Apache:
RewriteCond %{HTTP_HOST} example.com
RewriteRule (.*) http://www.example.com$1
When converting this to Nginx, it's best to split these rules into two separate server blocks in order to make things as efficient as possible. For example:
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# ...
}
Knowing how to convert Apache rules to Nginx properly does take time and experience. If you want to expedite the process, check out this htaccess to nginx converter.
That being said, don't assume that all conversion rules will be optimized for performance or even 100% correct. You'll need to at least have a basic understanding of converting these rules and they should always be double-checked when using an automated tool.
Summary
Having the ability to rewrite URLs in Nginx is an extremely powerful feature. Rewrite rules can go much further than simply redirecting a simple URL from its http version to its https version. However, learning how to properly implement these rules can take some time and requires some knowledge. To learn more about Nginx rewrite rules, check out this guide by Nginx themselves which provides various examples of the best ways to go about rewriting URLs in your Nginx configuration.