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