添加虛擬服務器
Nginx配置文件中至少包含一條定義虛擬服務器的server
指令。當Nginx處理一個請求時,第一個被選中的虛擬服務器將用于處理該請求。
虛擬服務器通過http
指令中的server
指令來定義,示例如下:
http {
server {
# 服務器配置
}
}
http
中可以包含多條server
指令來定義多個虛擬服務器。
通常server
指令中會包含一條listen
指令,用于指定該虛擬服務器將要監聽的IP地址和端口
。示例如下:
server {
listen 127.0.0.1:8080;
# 其他配置
}
如果不填寫端口,則采用標準端口。如果不填寫ip地址,則監聽所有地址。如果缺少整條listen指令,則標準端口是80/tcp
,默認端口是8000/tcp
,由超級用戶的權限決定。
如果有多個server配置了相同的ip地址和端口,Nginx會匹配server_name
指令與請求頭部的host
字段。server_name
指令的參數可以是精確的文本、通配符或正則表達式。通配符可以在字符串的頭部、尾部或兩端包含*
,*
可以匹配任意字符。Nginx采用Perl格式的正則表達式,以~
開頭。以下是一個精確匹配的例子:
server {
listen 80;
server_name example.org www.example.org;
...
}
如果有多個server_name
匹配host
字段,Nginx根據以下規則選擇第一個相匹配的server
處理請求:
- 精確匹配
- 以
*
開始的最長通配符,如*.example.org
- 以
*
結尾的最長通配符,如mail.*
- 第一個匹配的正則表達式(根據在配置文件中出現的先后順序)
如果找不到任何與host
字段相匹配的server_name
,Nginx會根據請求端口將其發送給默認的server。默認server就是配置文件中第一個出現的server,也可以通過default_server
指定某個server為默認server,如下所示:
server {
listen 80 default_server;
...
}
配置Location指令
Nginx根據URL將請求發送給不同的代理,或處理不同的文件請求。由server
指令中的location
指令配置規則。
比如,可以為虛擬服務器配置三個location
指令,將一些請求發送給代理服務器#1,將另外一些請求發送給代理服務器#2,再由本地文件系統處理剩余請求。
Nginx會將請求的URL匹配所有的location
指令,請執行匹配location中的指令。每個location
指令中通常還會包含多條更為精細匹配的location
指令。
location
指令包含兩類參數:前綴字符串
和正則表達式
。請求要匹配前綴字符串的話,必須以前綴字符串開始。
以下例子中location參數匹配以/some/path/
開始的請求URI,如/some/path/document.html
(不匹配/my-site/some/path
,因為/some/path
不在起始位置)。
location /some/path/ {
...
}
~
用于匹配區分大小寫的正則表達式,~*
用于匹配不區分大小寫的正則表達式。下面例子匹配任意包含.html
或.htm
的URI。
location ~ \.html? {
...
}
Nginx先匹配前綴字符串,然后再匹配正則表達式。正則表達式擁有較高優先級,除非使用^~
修飾符。在所有前綴字符串中,Nginx會挑選最精確的那個,也就是最長最匹配的那個。詳細匹配過程如下:
- 匹配所有前綴字符串;
- 如果有一個
=
定義的精確匹配前綴字符串,停止繼續匹配; - 如果
^~
在最長匹配的前綴字符串之前,將忽略正則表達式; - 存儲最長的匹配前綴字符串;
- 匹配正則表達式;
- 找到第一個相匹配的正則表達,停止匹配過程,并執行該location指令;
- 如果沒有正則表達式匹配,則使用第4部存儲的最長前綴字符串;
=
修飾符的典型應用是匹配 /
請求。針對頻繁訪問/
的情況,將location
參數設置為= /
可以加速處理過程,因為整個匹配過程在第一條之后就結束了。
location = / {
...
}
location
指令內可以配置如何處理請求:處理靜態文檔或將請求轉發給代理服務器。在下面的例子中,匹配第一個location
的請求可以訪問/data
目錄的文件,匹配第二個location
的請求將被轉發到www.example.com
服務器。
server {
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
}
其中root
指令指定了靜態文件的文件系統路徑,將與請求URI一起構成靜態文件的完全路徑。在上述例子中,請求/images/example.png
將返回服務器上位于/data/images/example.png
的文件。
proxy_pass
指令將請求轉發到代理服務器,并將代理服務器的響應返回給客戶端。在上述例子中,所有不是以/images/
開頭的URI請求都將被轉發到代理服務器。
使用變量
通過在配置文件中使用變量,可以讓Nginx以不同的方式處理請求。變量的值在運行時計算獲得,并可作為參數傳遞給指令。變量必須以$
開頭。變量基于Nginx的狀態定義信息,如正被處理請求的屬性。
Nginx包含許多預設的變量,如core HTTP
變量集,也可以使用set
、map
和geo
指令來自定義變量。大多數變量都在運行時計算值,這些值一般都包含某個請求的相關信息。如$remote_addr
包含了IP地址,而uri
則包含了當前訪問的URI
。
返回指定狀態碼
有些網站在處理錯誤或重定向時,會要求立即返回一個狀態碼。最簡單的方式就是使用return
指令,如下所示:
location /wrong/url {
return 404;
}
return
指令的第一個參數是一個狀態碼。第二個是可選參數,可以是重定向的URL(當狀態碼是301、302、303和307時),也可以是返回的文本信息。示例如下:
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
location
和server
中都可以包含return
指令。
重寫請求中的URI
在處理請求過程中,可以通過rewrite
指令重復修改請求的URI。rewrite
指令包含2個必填參數和1個可選參數。第一個參數是請求URI必須匹配的正則表達式。第二個參數是要替換的目標URI。第三個為可選參數,可以是一個是否繼續執行后續rewrite
指令的標記,也可以發送一個重定向指令(狀態碼是301或302)。示例如下:
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
location
和server
中都可以包含多個rewrite
指令。Nginx從上到下依次磁性rewrite
指令,每次進入server
指令塊時,rewrite
指令都會被執行一次。
Nginx執行完一系列rewrite
指令后,根據最新的URI來選擇location
指令。如果location
中也包含rewrite
指令,它們也將被依次執行,執行完畢后將重新選擇location
。
下面是一個rewrite
和return
聯合一起使用的例子。
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
這個例子用于區分兩套不同的URI。類似于/download/some/media/file
的URI將被改寫為/download/some/mp3/file.mp3
。由于最后的標識last
,Nginx將忽略隨后的兩條指令,然后以新的URI繼續處理請求。同樣地,類似于/download/some/audio/file
的URI將被改寫為/download/some/mp3/file.ra
。如果請求URI都不匹配上述兩條rewrite
指令,Nginx將返回403錯誤代碼。
rewrite
指令可以包含以下兩種參數,用于中斷處理過程:
- last - 停止執行當前
server
或location
中的rewrite
指令,并以新的URI查找新的location; - break - 停止執行當前上下文環境內的
rewrite
指令,并不以新的URI查找新的location;
重寫HTTP返回信息
sub_filter
指令支持重寫或修改HTTP請求的響應內容,如替換某個字符串。該指令支持變量和鏈式替換。
下例中,將指向服務器的鏈接改為指向代理服務器的鏈接:
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
另一個例子是將http請求改為https請求,并將請求頭部的本地主機地址改為主機名。sub_filter_once
指令用于告訴Nginx是否連續執行location
中的sub_filter
指令。
location / {
sub_filter 'href="https://$host/';
sub_filter 'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
sub_filter_once on;
}
注意:被sub_filter
指令修改后的內容將不會再被其他sub_filter
指令修改。
錯誤處理
error_page
指令用于返回一個自定義錯誤頁面和一個錯誤代碼、修改響應中的錯誤代碼或重定向到不同的URI。在下面的例子中,error_page
指令返回404錯誤和一個錯誤頁:
error_page 404 /404.html;
注意:該指令并不會馬上返回(這是return
指令做的事),僅僅指定出錯時如何處理。錯誤代碼可以能來自于代理服務器,也可能來自Nginx本身(如Nginx沒有找到請求的文件)。
在下面的例子中,當Nginx未能找到請求的頁面時,不會返回404,而會返回303和一個重定向到新頁面指令。這通常用于處理客戶端訪問舊地址的情況。
location /old/path.html {
error_page 404 =301 http:/example.com/new/path.html;
}
以下例子中,當訪問一個不存在的文件時,Nginx會將請求重定向到http://backend
。由于error_page
指令未指定重定向代碼,該代碼將由重定向后的http://backend
返回。
server {
...
location /images/ {
# Set the root directory to search for the file
root /data/www;
# Disable logging of errors related to file existence
open_file_cache_errors off;
# Make an internal redirect if the file is not found
error_page 404 = /fetch$uri;
}
location /fetch/ {
proxy_pass http://backend/;
}
}
在上述例子中,當請求文件未找到時,error_page
指令將發起一個內部重定向。$url變量持有當前請求的URI,并被傳遞給重定向。
假設請求的/images/some/file
文件未找到,將被重定向到/fetch/images/some/file
,同時搜索新的location
。最終,請求將被第二個location
處理,并被代理到http://backend
。
open_file_cache_errors
指令可用于未找到請求文件時,禁止產生錯誤消息。在上述例子中可以忽略,因為錯誤已被正確處理。