Pratik Devkota
Pratik Devkota
I am a software engineering student interested in UNIX (GNU/Linux, *BSD, etc.), security as well as free and open-source software.

Nginx – Virtual Hosts (Part 3)

- Advertisement -

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.

Nginx variables

Don’t forget to check the configuration with nginx -t and reload with nginx -s reload.

Testing nginx variables

Notice that the arguments is currently empty. Well, that’s because we haven’t provided it any.

Testing with arguments

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:

Nginx $arg_name

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:

Using conditionals for configuration
Nginx conditionals 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:

Basic redirect
Default index

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.

Received 307 from nginx

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.

Rewrite Example

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.

Welcome messages

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:

Welcome messages configuration

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.

- Advertisement -

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest articles

Join us on Facebook

x