Objective : Understanding Nginx Server and Location Block Selection Algorithms with Examples.
Environment : Ubuntu 14.04 LTS.
Installation
Open terminal, type :
$ sudo apt-get update
$ sudo apt-get install nginx
Nginx Configuration Blocks
Nginx logically divides the configurations meant to serve different content into blocks, which live in a hierarchical structure. The main blocks that we will be discussing are the server block and the location block
A server block is a subset of Nginx's configuration that defines a virtual server used to handle requests of a defined type. Often based on the requested domain name, port, and IP address.
A location block lives within a server block and is used to define how Nginx should handle requests for different resources and URIs for the parent server. Extremely flexible model.
Server Block
Server Block Selection Algorithm
Nginx allows to define multiple server blocks that function as separate virtual web server instances, through a defined system of checks that are used to find the best possible match.
To decide which server block will handle the request Nginx will parse listen Directive first then server_name Directive (only if needed).
Parsing the "listen" Directive to Find Possible Matches
Nginx default value is 0.0.0.0:80 (or 0.0.0.0:8080)
The listen directive typically defines which IP address & port that the server block will respond to. Listen directive can be set to :
- An IP address/port combo, e.g.:
192.168.0.11:8080
- A lone IP address, e.g.:
192.168.0.11
- A lone port which will listen to every interface on that port, e.g.:
*:8080
- The path to a Unix socket(generally only have implications when passing requests between different servers).
To determine which server block to send a request to, Nginx will first try to decide based on the specificity of the listen directive using the following rules:
- Nginx translates all "incomplete" listen directives by substituting missing values with their default values so that each block can be evaluated by its IP address and port, e.q. : A block with no listen directive uses the value 0.0.0.0:80.
- Nginx then attempts to collect a list of the server blocks that match the request most specifically based on the IP address and port. Block that is functionally using 0.0.0.0 as its IP address (to match any interface), will not be selected if there are matching blocks that list a specific IP address.
- If there is only one most specific match, that server block will be used to serve the request. If there are multiple server blocks with the samex level of specificity matching -> begin to evaluate the server_name directive of each server block.
Nginx will only evaluate the server_name directive, if server blocks has same level of specificity of listen directive.
Parsing the "server_name" Directive to Choose a Match
To evaluate requests that have equally specific listen directives, Nginx checks the request's "Host" header. This value holds the domain or IP address that the client was actually trying to reach.
Nginx will find best match of server_name directive within each selected server blocks with following rules in order :
- If multiple exact matches of server_name(s) are found, the first one is used.
- If no match found, Nginx find a server block with a server_name that matches using a leading wildcard (indicated by a * at the beginning of the name in the config).
- If no match is found, Nginx uses a trailing wildcard.
- If no match is found, uses regular expressions (indicated by a ~ before the name)
- If none are able to satisfy the request, the request will be passed to the default server for the matching IP address and port.
Example :
server {
listen 80;
server_name example.com;
. . .
}
Location Block
Location Block Syntax
Location blocks live within server blocks (or other location blocks), used to decide how to process the request URI (the part of the request that comes after the domain name or IP address/port).
The location_match in the example below defines what Nginx should check the request URI against :
location optional_modifier location_match {
...
}
Location Block Selection Algorithm
- (none) : Prefix matching.If no modifiers are present, the location is interpreted as a prefix match. This means that the location given will be matched against the beginning of the request URI to determine a match. Example: location block below may be selected to respond for request URIs : /site, /site/page1/index.html, or /site/index.html
location /site {
. . .
}
- = : Exact matching. If an equal sign is used, this block will be considered a match if the request URI exactly matches the location given. Example : block below will always be used to respond to : /page1. Will not be used to respond : /page1/index.html request URI. Keep in mind that if this block is selected and the request is fulfilled using an index page, an internal redirect will take place to another location that will be the actual handler of the request.
location = /page1 {
. . .
}
- ~ : Case-sensitive regex matching, if a tilde modifier is present. Block below could be used to handle requests for /tortoise.jpg, but not for /FLOWER.PNG.
location ~ \.(jpe?g|png|gif|ico)$ {
. . .
}
- ~* : Case-insensitive regex matching, if a tilde and asterisk modifier is used. Both /tortoise.jpg and /FLOWER.PNG could be handled by this block :
location ~* \.(jpe?g|png|gif|ico)$ {
. . .
}
- ^~: If a carat and tilde modifier is present, and if this block is selected as the best non-regular expression match, regular expression matching will not take place.
Source :