Introduction
This is a continuation of my previous series of articles. So you might want to check that out first.
In the previous article, we’ve left off with nginx returning basic responses to a given URI match. Let’s look into what more we can do.
Nginx Variables
Nginx comes with its own set of variables that we can use in our configuration. The list of all the variables is available in their documentation. We’re going to have a look at few of those.
- host – This evaluates to the host name specified in the URL, or the value of “Host” header field in the request, or the server name matching the request.
- uri – This is the URI that matched the request.
- args – This contains the arguments supplied in the URL in the form of key-value pairs.
We access these variables with the $
symbol prepended, like in PHP.
Let’s see this in action with a simple example.
Don’t forget to check the configuration with nginx -t
and reload with nginx -s reload
.
Notice that the arguments is currently empty. Well, that’s because we haven’t provided it any.
The supplied arguments (i.e. the string after the ?
character) are contained in the $args
variable. Also note how the value of $host
changed when I supplied the IP address of the nginx instance instead of the domain name. Nginx also initialises variables with the name $arg_<name>
where the <name>
is the name of argument supplied in the URI. So in the above example, nginx would have populated a variable $arg_hello
with the value world
.
Replacing $args
in the configuration with $arg_hello
gives:
We can also set our own variables with the following syntax:
set $<var_name> <var_value>;
Conditional statements in Nginx
Nginx also supports conditional statements . Let’s see how it works with an example:
Redirects and Rewrites
Now we can look at performing redirects. We can use two different directives to do this:
The Return Directive
Previously, we’ve used this directive to simply return a string. However, we can also supply a URI to match. This way, the current request is redirected to the given URI.
The way nginx determines whether a response is supposed to be a simple string or a redirect is by looking at the response code. We’ve seen that giving the response code of 200 makes nginx simply return a string whereas if it’s any of the 300 variants, then nginx interprets the next argument as a redirection.
Let’s look at an example:
Fetching the root URI gives us the default index file, as expected. However, when I try to request the /blog
URI. I receive a temporary redirect instead.
I will have to tell curl
to follow that redirect (where to go is being given by the Location field in the header) with the -L
flag.
So this is how redirection works. Now let’s have a look at the other type of directive.
The Rewrite Directive
While the return statement simply tells our client where to go instead, the rewrite directive modifies the URI internally and issues a new request for the modified URI. The rewrite directive takes two arguments: the first one is the URI to match against, and the second being the URI that will be rewritten. Let’s have a look at a simple example:
rewrite /test /rewritten;
So what we’re basically saying here is “if the request matches the /test
URI, then rewrite it as /rewritten
internally and re-evaluate the request from the top skipping past the rewrite statement.” This also means, we need a location block for /rewritten
defined.
location /rewritten {
return 200 "You are at $uri.\n";
}
Let’s try out this configuration.
Note that, with the /test
URI, we still get the value of $uri
as /rewritten
.
Putting It All Together
Now let’s try to combine all of what we’ve learned before into a single configuration.
Suppose I want to be able to serve welcome messages to requests with the /home/
URI. If the request contains a name
suffix i.e. if the URI is something like /home/<name>
, then I want to include the given name as an argument to a user
variable so that I can use that value in the welcome message. Otherwise I’ll just welcome the guest.
Here, I am simply returning the index file at the root URI, but the /home
URIs function as explained before.
The configuration to do so would be:
At line 17, I am defining a regex which matches for URIs starting with /home/
followed by any word characters. The parentheses around it defines a capture group. The matched regex will be rewritten as /home/?user=$1
where $1
is the simply the string that was matched by the first capture group in the previous regex. So now the new URI is tested against the location blocks below.
At line 21, I am defining an exact match which matches when there were no word characters after the initial /home
in which case we’ll simply welcome the guest.
At line 29, (which will be tested if the exact match didn’t succeed) I am using the value of the user
argument passed in the URI to welcome the user.
This concludes today’s article. Hope you learned something. Thanks for reading.