將NGINX配置爲Web服務器


    在較高的層次上,將NGINX配置爲web服務器需要定義它處理哪些url以及如何處理這些url上的HTTP資源請求。在較低的級別上,NGINX配置定義了一組虛擬服務器,用於控制對特定域或IP地址的請求的處理。
    每個HTTP虛擬服務器都定義了多個名爲location的特殊配置實例,用於控制URI的處理。每個location都定義了當請求被映射到該location時的方案。每個location都可以代理請求或返回相應文件。此外,可以修改URI,以便將請求重定向到另一個location或虛擬服務器。此外,還可以返回特定的錯誤代碼,並且可以根據每個錯誤代碼配置特定頁面。

1. 設置虛擬服務器

    NGINX配置文件至少需要一個server指令,用於定義一個虛擬服務器。當NGINX處理請求時,它首先選擇處理請求的虛擬服務器。
    一個虛擬服務器由http上下文中的server指令來定義,例如:

http {
    server {
        # Server configuration
    }
}

    可以在http上下文中添加多個server指令來定義多個虛擬服務器。
    server配置塊通常包含一個listen指令,用於指定偵聽請求的服務器IP地址和端口。接受IPv4和IPv6地址。IPv6地址需要括在方括號中。
    下面的示例顯示偵聽IP地址127.0.0.1和端口8080的服務器配置:

server {
    listen 127.0.0.1:8080;
    # The rest of server configuration
}

    如果省略端口,則使用標準端口。同樣,如果省略地址,服務器將偵聽所有地址。如果根本不包括listen指令,標準端口是80/tcp,這取決於超級用戶權限。
    如果有多個服務器與請求的IP地址和端口匹配,nginx將請求報文的host頭部與server塊的server_name指令進行比對。server_name參數可以是一個完整的名稱,通配符或者正則表達式。通配符是一種字符串,可以在開始,結尾或兩者包含星號(*)。星號匹配任何字符序列。nginx使用perl語法的正則表達式,在它們前面加上波形號(~)。示例列舉了一個準確的名字:

server {
    listen      80;
    server_name example.org www.example.org;
    #...
}

    如果多個名稱匹配請求的host報頭,nginx將按以下順序搜索名稱並使用找到的第一個匹配項:

  • 準確名稱
  • 以星號開頭的最長通配符,如*.example.org
  • 以星號結尾的最長通配符,如mail*
  • 第一個匹配的正則表達式(按在配置文件中出現的順序)

    如果host頭與任何服務器名稱都不匹配,nginx將請求路由到請求到達端口的默認服務器。一般默認服務器是nginx.conf文件中列出的第一個,除非你使用listen指令的default_server參數明確指定一臺服務器作爲默認服務器。

server {
    listen 80 default_server;
    #...
}

2. 配置locations

    NGNX可以基於請求URI向不同代理髮送業務或提供不同的文件。這些塊由server指令中的location指令定義。
    例如,你能定義3個location塊指導虛擬服務器將一部分請求發送到一臺代理服務器,其他請求發送到另一臺不同的代理服務器,通過本地文件系統提供文件來處理剩下的請求。
    NGINX比較着請求的URI和所有location指令的參數,並應用匹配location中的指令。在每個location塊,通常可以(除了少數例外)放置更多的location指令來進一步完善對特定請求組的處理。
    location指令有兩種類型的參數:前綴字符串(代表路徑名)和正則表達式。要使請求URI與前綴字符串匹配,它必須以前綴字符串開頭。
    下面的location示例帶有匹配請求URI的路徑名參數,該示例以 /some/path/ 開始,例如 /some/path/document.html。

location /some/path/ {
    #...
}

    對於區分大小寫的匹配,正則表達式前面是波形號 ~ ,對於不區分大小寫的匹配,前面是波形號加星號 ~* 。下面的示例匹配在任何位置包含string.html或.htm的URI(正則表達式?表示匹配前面的字母 l 零次或一次):

location ~ \.html? {
    #...
}

3. NGINX Location優先級

    爲了找到最匹配URI的location,NGINX首先將URI與location的前綴字符串對比。然後查找帶正則表達式的location。
    除非使用^~修飾符,否則正則表達式將具有更高的優先級。在前綴字符串中,NGINX選擇最具體的那個(最長,最完整的字符串)。選擇location的具體過程如下:

  • 將接收到的URI與所有前綴字符串逐一匹配;
  • = 意味着URI與前綴字符串完全匹配。如果出現完全匹配,停止繼續搜索;
  • 如果 ^~ 修飾符在最長的匹配前綴字符串前面,則不檢查正則表達式;
  • 存儲最長的匹配前綴字符串;
  • 將URI與正則表達式進行匹配;
  • 中斷第一個匹配的正則表達式並使用相應的location;
  • 如果沒有正則表達式匹配,使用與存儲的前綴字符串對應的location。

    = > ^~ >正則表達式 > 前綴字符串
     = 修飾符的典型應用是用於 / 的請求。如果 / 的請求很頻繁,在location指令中明確 =/ 的參數可以加速處理,因爲匹配的搜索在第一次比較後就會停止。

 location = / {
    #...
}

    location上下文可以包含如何處理請求的指令,這些指令類似:提供一個靜態文件或者將請求發往代理服務器。在下面的示例中,匹配第一個location上下文的請求會接收到/data文件夾提供的文件,匹配第二個location的請求會被轉發到 www.example.com 的代理服務器。

server {
    location /images/ {
        root /data;
    }

    location / {
        proxy_pass http://www.example.com;
    }
}

    root指令提供了查找相關靜態文件的系統路徑。與該location關聯的請求URI被附加到路徑中,以獲取要提供的靜態文件的全名。在上面的示例中,針對請求 /images/example.png,nginx提供文件/data/images/example.png。
    proxy_pass指令將請求傳遞到配置了URL訪問的代理服務器。來自代理服務器的響應被傳遞給客戶端。在上面的示例中,所有不以/images/開頭的請求都被傳遞給了代理服務器。

4. 使用變量

    你可以在配置文件中使用變量,通過定義環境,使nginx處理請求有所不同。變量在計算時被臨時賦值,也被用作指令的參數。變量名稱的開頭用 \ 符號表示。變量根據NGINX的狀態定義信息,例如當前正在處理的請求的屬性。
    有一些預定義的變量,例如$server_name這種核心HTTP變量。你可以使用set,map,geo指令來定義用戶變量。大多數變量是在運行時計算的,並且包含與特定請求有關的信息。例如, $remote_addr包含客戶端IP地址, $uri 包含當前URI值。

5. 返回特定狀態碼

    某些網站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;
}

    return指令可以同時包含在location和server上下文中。

6. 重寫請求中的URI

    通過使用rewrite指令,可以在請求處理期間多次修改請求URI。rewrite指令具有一個可選參數和兩個必需參數。第一個必需的參數是匹配請求URI的正則表達式,第二個參數是用於替換的URI。可選的第三個參數是一個標誌,它可以停止rewrite指令的進一步處理或者發送一個重定向(301或302碼)。例如:

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

    如上例所示,第二個參數users通過正則表達式獲得。
    你可以在server和location上下文中使用多個rewrite指令。NGINX會按指令出現順序依次執行。當上下文被選中後,server上下文中的rewrite指令會被執行一次。
    NGINX處理了一組重寫指令後,它會按照新URI選擇location上下文。如果選中的location包含rewrite指令,就依次執行。如果URI與任何一個都匹配,在所有已定義的rewrite指令被執行之後,將搜索新location。
    以下示例顯示了與return指令結合使用的rewrite指令:

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標誌,隨後的rewrite,return指令被忽略,但是NGINX繼續處理不同URI的請求。類似的,URI /download/some/audio/file 被替換成 /download/some/mp3/file.ra。如果URI不滿足任何一個rewrite指令,NGINX會向客戶端返回403錯誤碼。
    有兩個參數可以中斷rewrite指令的進程:

  • last 停止執行當前server或location上下文中的rewrite指令,但是NGINX查找匹配重寫的URI的location,並應用新location中的rewrite指令。(意味着URI能夠再次被改變)
  • break 類似break指令,停止當前上下文中的rewrite指令進程,取消查找匹配新URI的location。新location中的rewrite指令不會被執行。

7. 重寫HTTP響應

    有時,您需要重寫或更改HTTP響應中的內容,用一個字符串替換爲另一個字符串。您可以使用sub_filter指令定義要應用的重寫。該指令支持變量和替換鏈,從而使更復雜的更改成爲可能。
    例如,可以更改絕對鏈接,該鏈接引用代理以外的服務器:

location / {
    sub_filter      /blog/ /blog-staging/;
    sub_filter_once off;
}

虛擬主機配置文件如下:

server {
    listen 80;
    root /www ;
    location / {
         sub_filter      /blog/ /blog-staging/;
    }
}

默認首頁如下:

# cat /www/index.html 
<html>
/blog/ <br>
/blog-staging/
</html>

瀏覽器訪問結果:
在這裏插入圖片描述
    另一個示例將 http:// 方法更改爲 https:// 並將localhost地址替換爲請求報文頭的主機名。sub_filter_once 指令告訴NGINX在一個location內連續使用sub_filter:

location / {
    sub_filter     'href="http://127.0.0.1:8080/'    '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也不會再次被修改了。

8. 處理錯誤

    使用error_page指令,您可以配置NGINX以返回自定義頁面以及錯誤代碼,在響應中替換不同的錯誤代碼,或者將瀏覽器重定向到其他URI。在以下示例中,error_page指令指定要返回的頁面(/404.html),並附帶404錯誤代碼。

error_page 404 /404.html;

    請注意,此指令並不意味着立即返回錯誤(return指令這樣做),而只是指定錯誤發生時的處理方式。錯誤代碼可能來自代理服務器,也可能是在NGINX處理期間發生的(例如,NGINX無法找到客戶端請求的文件時返回404)。
    在下面示例中,當NGINX找不到頁面,它將代碼404替換爲301,並重定向客戶端到http:/example.com/new/path.html。當客戶端仍嘗試使用其舊URI訪問頁面時,此配置很有用。301代碼通知瀏覽器該頁面已永久移動,並且在返回時自動用新地址替換舊地址。

location /old/path.html {
    error_page 404 =301 http://example.com/new/path.html;
}

    下面的配置示例表示當文件找不到時,將請求傳遞給backend。由於在error_page指令中的等號後沒有指定狀態碼,因此對客戶端的響應使用代理服務器返回的狀態碼(不一定是404)。

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指令告知NGINX,當文件找不到時,進行一次內部重定向。error_page指令最後參數中的 $uri 變量保存當前請求的URI,並將其傳遞給重定向。
    例如,如果 /images/some/file 沒有找到,就會被替換爲 /fetch/images/some/file 並開始搜索相關location。最後,請求在第二個location上下文結束,並被代理到http://backend/。
    如果文件找不到,open_file_cache_errors指令可以防止寫入錯誤消息。這裏沒有必要這樣做,因爲丟失的文件已經被正確處理了。
    寫點東西真的好累鴨~~
在這裏插入圖片描述

參考文檔

https://docs.nginx.com/nginx/admin-guide/web-server/web-server/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章