3. Nginx web server配置

添加虛擬服務器

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處理請求:

  1. 精確匹配
  2. *開始的最長通配符,如*.example.org
  3. *結尾的最長通配符,如mail.*
  4. 第一個匹配的正則表達式(根據在配置文件中出現的先后順序)

如果找不到任何與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會挑選最精確的那個,也就是最長最匹配的那個。詳細匹配過程如下:

  1. 匹配所有前綴字符串;
  2. 如果有一個=定義的精確匹配前綴字符串,停止繼續匹配;
  3. 如果^~在最長匹配的前綴字符串之前,將忽略正則表達式;
  4. 存儲最長的匹配前綴字符串;
  5. 匹配正則表達式;
  6. 找到第一個相匹配的正則表達,停止匹配過程,并執行該location指令;
  7. 如果沒有正則表達式匹配,則使用第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變量集,也可以使用setmapgeo指令來自定義變量。大多數變量都在運行時計算值,這些值一般都包含某個請求的相關信息。如$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;
}

locationserver中都可以包含return指令。

重寫請求中的URI

在處理請求過程中,可以通過rewrite指令重復修改請求的URI。rewrite指令包含2個必填參數和1個可選參數。第一個參數是請求URI必須匹配的正則表達式。第二個參數是要替換的目標URI。第三個為可選參數,可以是一個是否繼續執行后續rewrite指令的標記,也可以發送一個重定向指令(狀態碼是301或302)。示例如下:

location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
}

locationserver中都可以包含多個rewrite指令。Nginx從上到下依次磁性rewrite指令,每次進入server指令塊時,rewrite指令都會被執行一次。

Nginx執行完一系列rewrite指令后,根據最新的URI來選擇location指令。如果location中也包含rewrite指令,它們也將被依次執行,執行完畢后將重新選擇location

下面是一個rewritereturn聯合一起使用的例子。

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 - 停止執行當前serverlocation中的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指令可用于未找到請求文件時,禁止產生錯誤消息。在上述例子中可以忽略,因為錯誤已被正確處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容