Mahdi.Kh
September 21, 2026
The rewrite and redirect directives are typically used to build more meaningful URLs, or to send users to new addresses.
Using the rewrite and return directives, you can show the user different content while keeping the current address, or send the user to a new address.
The return directive ends the request's processing and returns a status code to the user (documentation). This directive can be used inside if, location, and server blocks.
Using one of the status codes 301, 302, 303, 307, or 308, you can specify a URL as the second parameter so the user is directed to that address (a redirect is performed). If a different status code is used, you can send whatever content you want as the second parameter, so it's treated as the response body in the response to the user.
In the example above, if you open localhost:8065 or 127.0.0.1:8065 in your browser, you should be redirected to /home right away, and then the response we specified is shown. Also, if you go to /downloads, you'll get status code 404.
Using the rewrite directive, besides redirecting to a new address, you can also send the request to a different path while keeping the current address.
This directive's general structure is as follows (documentation):
As we can see, this directive takes a PCRE-type pattern as its first parameter, the second parameter is the path we want to replace it with, and finally a flag can be used at the end if needed.
Using a flag causes the processing of the current directives to stop and not continue. The flags we can use are as follows:
If you use redirect, a redirect with status code 302 is performed. This is used when the path we specify as the replacement doesn't start with , , or .
http://https://$schemeIf the path we specify as the replacement starts with https://, http://, or $scheme, the result is the same as using the redirect flag, and there's no need to use this flag.
In the example above, using the rewrite_log directive, we enabled logging for rewrite directives. If we go to /hello-man, we're redirected to /hello-world with status code 302. This means the URL in the browser will change from /hello-man to /hello-world.
Also, if you go to /hello-woman, you're directed to hello-world. Here, the address contains http://, which causes the redirect to happen with status code 302.
Using rewrite, you can redirect traffic for one path to another path; take a look at the example below:
In the example above, we redirected traffic for /welcome requests to /bye. If the user goes to /welcome, the address in the browser will change to /bye.
This flag behaves like the redirect flag, except the status code changes to 301. If you want to set up a permanent redirect, it's better to use this flag.
The difference between the redirect and permanent flags is the status code they return when redirecting.
This flag rewrites the address, stops the execution of other rewrite directives, and starts matching against a new location that matches the changed address.
Unlike the redirect and permanent flags, when you use the last flag, the user's browser address doesn't change; instead, the address rewriting happens inside nginx. That is, while keeping the address entered in the browser, the request is answered from a different address.
Following the example above, if you go to /hello-man in your browser, while the address is kept as is, data from /hello-world will be loaded for you.
Following the example above, if we go to /hello-man, this address matches the first rewrite, and because this rewrite has a flag (last, here), the rest of the rewrites in the current block (server, here) won't be matched, and the request is rewritten to /hello-world. The request is then reviewed again as if it were a new request, and since the address has changed to /hello-world, the second rewrite matches, and the request is rewritten to /bye, and in the end we'll see Bye bye on the page.
This flag rewrites the address and stops the execution of other rewrite directives, but unlike last, it doesn't do a new match against location blocks. So if this flag is used inside a location block, request processing continues within that same location, and no new match is performed.
Following the example above, if we open 127.0.0.1:8066/hello-man in the browser, the first rewrite is performed, which causes the remaining rewrites to not be processed. And since no new match is done against the rewritten address, the second rewrite never runs, and the request is ultimately processed through the /hello-world path.
If no flag is specified, the address is rewritten, but the execution of the other rewrites doesn't stop. That is, if we have several rewrites, all of them, if matched, run one after another from top to bottom, and if no response is returned by the following directives, Nginx finally tries again to match a suitable location based on the rewritten address.
In the example above, if we go to /goodbye1, the request will be loaded from /welcome. But if we go to /goodbye2, the text goodbye is shown to us on the page from that same path.
Using the set directive, you can create a variable and assign it a value. Variables in nginx are denoted with a dollar sign, $. To create a variable, you can do it like the example below:
The value inside a variable is always treated as text. If the value you want contains a space character or ;, you need to wrap your value in single or double quotes.
Using the if directive, you can run some code when a condition holds. Its general structure is as follows:
Here, condition is the condition we want, and if it evaluates to true, the code inside the if body will run. (documentation)
=, and for inequality, !=.~ and a regex for a match. This is case-sensitive.*~ and a regex for a match. This isn't case-sensitive.0, it's treated as false.In most cases, we use the four approaches above for comparisons. You can read about more complex cases in Nginx's documentation.
Based on the code above, if you add ?name= to the address and give it a value, that value is shown on the page. Otherwise, the text hello world is shown on the page. For example, if we go to 127.0.0.1:8070?name=mahdi, the text Hello mahdi is shown on the page.
In this code, we first defined a variable named $name, and using $arg_name, we put the value of the query string parameter named name into this variable. Then, inside the location body, if $name is empty, we default it to world. This way, if we don't pass a name via the query string, Hello world is shown, and otherwise, Hello together with the name we wanted is shown on the page.
Nginx has a number of built-in variables, and you can see the list of them in the documentation; if needed, you can check the documentation and use whichever variable you want.
You can access the code we covered in this part through our GitHub repository.
Previous part: Caching | Nginx from Scratch