1. 程式人生 > >ASP.NET Core應用針對靜態檔案請求的處理[2]: 條件請求與區間請求

ASP.NET Core應用針對靜態檔案請求的處理[2]: 條件請求與區間請求

通過呼叫ApplicationBuilder的擴充套件方法UseStaticFiles註冊的StaticFileMiddleware中介軟體幫助我們處理針對檔案的請求。對於StaticFileMiddleware處理請求的邏輯,大部分讀者都應該想得到:它根據請求的地址找到目標檔案的路徑,然後利用註冊的ContentTypeProvider根據路徑解析出與檔案內容相匹配的媒體型別,預設情況下得到的媒體型別是根據目標檔案的副檔名解析出來的。解析出來的媒體型別將作為響應報頭Content-Type的值。StaticFileMiddleware中介軟體最終利用FileProvider讀取檔案的內容作為響應訊息的主體。實際上,這個中介軟體在處理請求時比我們想象的要多得多,針對條件請求(Conditional Request)

區間請求(Range Request)的處理就沒有在上面演示的例項中體現出來。 [本文已經同步到《ASP.NET Core框架揭祕》之中]

目錄
一、條件請求
    HTTP條件請求
    針對靜態檔案的條件請求
二、 區間請求
    HTTP區間請求
    針對靜態檔案的區間請求

一、條件請求

所謂的條件請求就是客戶端在傳送GET請求獲取某種資源的時候,會利用請求報頭攜帶一些條件。服務端處理器在接受到這樣的請求之後,會提取這些條件並驗證目標資源的當前的狀態是否滿足客戶端指定的條件。在有在這些條件滿足的情況下,目標資源的內容才會真正響應給客戶端。

HTTP條件請求

HTTP條件請求作為一項標準記錄在HTTP規範中。一般來說,一個GET請求在目標資源存在的情況下總是會返回一個狀態為“200 OK”的響應,目標資源的內容將直接存放在響應訊息的主體部分。如果資源的內容不會輕易改變,我們希望客戶端(比如瀏覽器)在本地快取獲取的資源。對於由它傳送的針對同一資源的後續請求,如果資源內容不曾改變,那麼資源的內容則無需再次作為網路負載予以響應。這就是條件請求需要解決的一個典型場景。

確定資源是否發生變化可以採用兩種策略。第一種就是讓資源的提供者記錄下最後一次更新資源的時間,資源的負載和這個時間戳將一併作為響應提供給作為請求傳送者的客戶端。客戶端在快取資源自身內容的同時也會儲存這個時間戳。等到下次針對同一資源傳送請求,它會將這個時間戳一併傳送出去,那麼服務端就可以根據這個時間戳判斷目標資源在上次響應之後是否被修改過。除了採用記錄資源最後修改時間的方式外,我們還可以針對資源的內容生成一個“簽名”,簽名的一致性體現了資源內容的一致性,在HTTP規範中將這個簽名成為ETag(Entity Tag)。

接下來我們從HTTP請求和響應報文的層面對條件請求進行詳細介紹。對於HTTP請求來說,快取資源攜帶的最後修改時間戳

ETag分別儲存在名為If-Modified-SinceIf-None-Match的報頭中。報頭名稱體現的意思是如果目標資源在指定的時間之後被修過(If-Modified-Since)或者目前資源的狀態與提供ETag的不匹配(If-None-Match)才將目標資源的內容作為響應負載返回。

當服務端接收到針對某個資源的GET請求,如果請求不具有上述這兩個報頭或者根據這兩個報頭攜帶的資訊判斷資源已經發生改變,在的情況下會返回一個狀態碼為“200 OK”的響應。除了將資源內容作為響應主體之外,如果能夠獲取到該資源最後一次修改的時間(一般精確到秒),格式化的時間戳將儲存到一個名為Last-Modified的報頭中。至於針對資源自身內容生成的簽名,對應的報頭名稱就是ETag。反之,如果做出相反的判斷,服務端會響應一個狀態碼為“304 Not Modified”的響應,這個響應不具有主體。一般來說,這樣的響應也會攜帶Last-Modified和ETag報頭。

與條件請求相關的請求報頭還具有額外兩個,即If-Unmodified-Since和If -Match,它們具有與If-Modified-Since和If-None-Match完全相反的語義,分別表示如果目標資源在指定時間之後沒有被修改(If-Unmodified-Since)或者目標資源目前的ETag與提供的ETag匹配(If-Match)的請求下才將資源作為響應負載返回。針對這樣的請求,如果根據攜帶的這兩個報頭判斷出目標資源並不曾發生變化,服務端會返回一個將資源內容作為主體的“200 OK”響應,這樣的響應也會攜帶Last-Modified和If-Match報頭。反之,如果做出了相反的判斷,服務端會響應一個狀態碼為“412 Precondition Failed”的響應。

針對靜態檔案的條件請求

接下來我們通過例項演示的形式來介紹StaticFileMiddleware中介軟體在針對條件請求方面做了些什麼。假設我們在ASP.NET Core應用中釋出一個文字檔案(foobar.txt),內容為“abcdefghijklmnopqrstuvwxyz0123456789”(26個字母+10個數字),目標地址為“http://localhost:5000/foobar.txt”。現在我們直接利用Fiddler針對這個地址傳送一個普通的GET請求,看看會得到怎樣的響應。

   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000
   3:  
   4: HTTP/1.1 200 OK
   5: Date: Thu, 10 Nov 2016 13:01:59 GMT
   6: Content-Length: 39
   7: Content-Type: text/plain
   8: Server: Kestrel
   9: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  10: Accept-Ranges: bytes
  11: ETag: "1d23af3dad4aaa7"
  12:  
  13: abcdefghijklmnopqrstuvwxyz0123456789
從上面給出的請求與響應報文的內容可以看出,對於一個針對物理檔案的GET請求,如果目標檔案存在,伺服器會返回一個狀態碼為“200 OK”的響應。除了承載著檔案內容的主體外,響應報文還具有兩個額外的報頭,它們分別是表示目標檔案最後一次修改時間的Last-Modified和作為檔案簽名的ETag。

現在客戶端不但獲得了目標檔案的內容,還得到了該檔案最後被修改的時間戳和簽名,如果它只想確定這個檔案是否被更新,並在在更新之後返回新的內容,那麼它可以針對這個檔案所在的地址再次傳送一個GET請求,並將這個時間戳和簽名通過相應的請求報頭髮送給服務端,我們知道這兩個報頭的名稱分別是If-Modified-Since和If-None-Match。由於我們沒有修改檔案的內容,所以伺服器返回如下一個狀態為“304 Not Modified”的響應,這個不包括主體的響應同樣具有相同的Last-Modified和ETag報頭。

   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000
   3: If-Modified-Since: Thu, 10 Nov 2016 01:43:37 GMT
   4: If-None-Match: "1d23af3dad4aaa7"
   5:  
   6: HTTP/1.1 304 Not Modified
   7: Date: Thu, 10 Nov 2016 13:23:04 GMT
   8: Content-Type: text/plain
   9: Server: Kestrel
  10: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  11: Accept-Ranges: bytes
  12: ETag: "1d23af3dad4aaa7"

如果我們將If-None-Match報頭修改成一個較早的時間戳,或者改變了If-None-Match報頭的簽名,服務端都將做出檔案已經被修改的判斷。在這種情況下,最初那個狀態碼為“200 OK”的響應又會再次被返回,具體請求和對應的響應體現在如下所示的程式碼片段中。

   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000
   3: If-Modified-Since: Wed, 09 Nov 2016 01:43:37 GMT
   4: If-None-Match: "1d23af3dad4aaa7"
   5:  
   6: HTTP/1.1 200 OK
   7: Date: Thu, 10 Nov 2016 13:30:25 GMT
   8: Content-Length: 39
   9: Content-Type: text/plain
  10: Server: Kestrel
  11: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  12: Accept-Ranges: bytes
  13: ETag: "1d23af3dad4aaa7"
  14:  
  15: GET http://localhost:5000/foobar.txt HTTP/1.1
  16: Host: localhost:5000
  17: If-Modified-Since: Thu, 10 Nov 2016 01:43:37 GMT
  18: If-None-Match: "abc123xyz456"
  19:  
  20: HTTP/1.1 200 OK
  21: Date: Thu, 10 Nov 2016 13:31:49 GMT
  22: Content-Length: 39
  23: Content-Type: text/plain
  24: Server: Kestrel
  25: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  26: Accept-Ranges: bytes
  27: ETag: "1d23af3dad4aaa7"
  28:  
  29: abcdefghijklmnopqrstuvwxyz0123456789

如果客戶端想確定目標檔案是否被修改,但是希望在未被修改的情況下才返回目標檔案的內容,這樣的請求需要使用If-Unmidified-Since和If-Match報頭來承載基準時間戳和簽名。比如對於如下兩個請求攜帶的If-Unmidified-Since和If-Match報頭,服務段都將作出檔案尚未被修改的判斷,所以檔案的內容通過一個狀態為“200 OK”的響應返回。  
   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000
   3: If-Unmodified-Since: Fri, 11 Nov 2016 01:43:37 GMT
   4:  
   5: HTTP/1.1 200 OK
   6: Date: Thu, 10 Nov 2016 13:46:32 GMT
   7: Content-Length: 39
   8: Content-Type: text/plain
   9: Server: Kestrel
  10: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  11: Accept-Ranges: bytes
  12: ETag: "1d23af3dad4aaa7"
  13:  
  14: abcdefghijklmnopqrstuvwxyz0123456789
  15:  
  16: GET http://localhost:5000/foobar.txt HTTP/1.1
  17: Host: localhost:5000
  18: If-Match: "1d23af3dad4aaa7"
  19:  
  20: HTTP/1.1 200 OK
  21: Date: Thu, 10 Nov 2016 13:47:42 GMT
  22: Content-Length: 39
  23: Content-Type: text/plain
  24: Server: Kestrel
  25: Last-Modified: Thu, 10 Nov 2016 01:43:37 GMT
  26: Accept-Ranges: bytes
  27: ETag: "1d23af3dad4aaa7"
  28:  
  29: abcdefghijklmnopqrstuvwxyz0123456789

如果目標檔案當前的狀態不能滿足If-Unmidified-Since或者If-Match報頭體現的條件,那麼返回的將是一個狀態為“412 Preconception Failed”的響應,如下所示的就是兩條這樣的請求和對應響應的內容。

   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000
   3: If-Unmodified-Since: Wed, 9 Nov 2016 01:43:37 GMT
   4:  
   5: HTTP/1.1 412 Precondition Failed
   6: Date: Thu, 10 Nov 2016 13:54:09 GMT
   7: Content-Length: 0
   8: Server: Kestrel
   9:  
  10: GET http://localhost:5000/foobar.txt HTTP/1.1
  11: Host: localhost:5000
  12: If-Match: "abc123xyz456"
  13:  
  14: HTTP/1.1 412 Precondition Failed
  15: Date: Thu, 10 Nov 2016 13:55:31 GMT
  16: Content-Length: 0
  17: Server: Kestrel

二、 區間請求

大部分針對物理檔案的請求都是希望獲取整個檔案的內容,區間請求則使我們可以獲取某個檔案部分割槽間的內容。區間請求使我們可以通過多次請求來獲取某個較大檔案的內容,並實現斷點續傳。如果同一個檔案同時存放到多臺伺服器,我們可以利用區間請求同時下載不同部分的內容。和條件請求一樣,區間請求也是作為標準定義在HTTP規範之中。

HTTP區間請求

如果我們下希望通過一個GET請求獲取目標資源的某個區間的內容,那麼我們會將這個區間存放到一個名為Range的報頭中。雖然HTTP規範允許指定多個區間,但是StaticFileMiddleware中介軟體只支援單一區間。至於分割槽所採用的的計量單位,HTTP規範並未作強制的規定,但是StaticFileMiddleware支援的程式碼為“bytes”,也就是說它是以位元組為單位對檔案內容進行分割槽的。

Range報頭攜帶的分割槽資訊採用的格式為“bytes={from}-{to}”({from}和{to}分別表示區間開始和結束的位置),比如“bytes=1000-1999”表示獲取目標資源從1001到2000共計1000個位元組(第1個位元組的位置為0)。如果{to}大於整個資源的長度,這樣的區間被認為是有效的,意味著區間從{from}到資源的最後一個位元組。如果區間被定義成“bytes={from}-”這種形式,同樣表示區間從{from}到資源的最後一個位元組。採用“bytes=-{n}”這種格式定義的區間則表示資源的最後n個位元組。不論採用何種形式,如果{from}大於整個資源的總長度,這樣的定義都是不合法的定義了。

如果請求的Range報頭攜帶一個不合法的區間,服務端回返回一個狀態碼為“416 Range Not Satisfiable”的響應,否則會返回一個狀態為“206 Partial Content”的響應,響應的主體將只包含指定區間的內容。返回的內容在整個資源的位置通過響應報頭Content-Range表示,採用的格式為“{from}-{to}/{length}”。除此之外,還有一個與區間請求相關的響應報頭“Accept-Ranges”,它表示服務端能夠接受區間型別。比如前面針對條件請求的響應都具有這樣一個報頭“Accept-Ranges: bytes”,表示服務支援針對資源的區間劃分,該報頭的值為“none”,則意味著服務端不支援區間請求。

區間請求在某些時候也會去驗證資源內容是否發生改變。在這種情況下,請求會利用一個名為If-Range的報頭攜帶一個基礎時間戳或者整個資源(不是當前請求的區間)的簽名。服務端在接收到請求之後會根據這個報頭判斷請求的整個資源是否發生變換,如果判斷的結果是已經發生改變,它會返回一個狀態碼為“200 OK”的響應,響應主體將會包含整個資源的內容。只有在判斷資源並未發生變化的前提下,服務端再會返回指定區間的內容。

針對靜態檔案的區間請求

接下來我們照理從HTTP請求和響應報文的角度來探討StaticFileMiddleware中介軟體針對區間請求的支援。我們依然沿用前面演示條件請求的那個例子,這個例子中作為目標檔案的foobar.txt包含26個字母和10個數字,加上UTF文字檔案初始的三個字元(EF BB BF),所以總長度為39。我們利用Fiddler傳送如下兩個請求分別獲取前面26個字母(3-28)和後面10個數字(-10)。

   1: GET http://localhost:5000/foobar.txt HTTP/1.1
   2: Host: localhost:5000

            
           

相關推薦

ASP.NET Core應用針對靜態檔案請求處理[3]: StaticFileMiddleware中介軟體如何處理針對檔案請求

我們通過《以Web的形式釋出靜態檔案》和《條件請求與區間請求》中的例項演示,以及上面針對條件請求和區間請求的介紹,從提供的功能和特性的角度對這個名為StaticFileMiddleware的中間進行了全面的介紹,接下來我們將更近一步,將從實現原理的角度來進一步認識這個中介軟體。 [本文已經同步到《ASP.NE

ASP.NET Core應用針對靜態檔案請求處理[2]: 條件請求區間請求

通過呼叫ApplicationBuilder的擴充套件方法UseStaticFiles註冊的StaticFileMiddleware中介軟體幫助我們處理針對檔案的請求。對於StaticFileMiddleware處理請求的邏輯,大部分讀者都應該想得到:它根據請求的地址找到目標檔案的路徑,然後利用註冊的Cont

ASP.NET Core應用針對靜態檔案請求處理[1]: 以Web的形式釋出靜態檔案

雖然ASP.NET Core是一款“動態”的Web服務端框架,但是在很多情況下都需要處理針對靜態檔案的請求,最為常見的就是這對JavaScript指令碼檔案、CSS樣式檔案和圖片檔案的請求。針對不同格式的靜態檔案請求的處理,ASP.NET Core為我們提供了三個中介軟體,它們將是本系列文章論述的重點。不過在

ASP.NET Core應用針對靜態檔案請求處理[4]: DirectoryBrowserMiddleware中介軟體如何呈現目錄結構

和StaticFileMiddleware中介軟體一樣,DirectoryBrowserMiddleware中間本質上還是定義了一個請求地址與某個物理目錄之間的對映關係,而目標目錄體現為一個FileProvider物件。當這個中介軟體接收到匹配的請求後,會根據請求地址解析出對應目錄的相對路徑,並利用這個Fil

ASP.NET Core應用針對靜態檔案請求處理[5]: DefaultFilesMiddleware中介軟體如何顯示預設頁面

DefaultFilesMiddleware中介軟體的目的在於將目標目錄下的預設檔案作為響應內容。我們知道,如果直接請求的就是這個預設檔案,那麼前面介紹的StaticFileMiddleware中介軟體會將這個檔案響應給客戶端。如果我們能夠將針對目錄的請求重定向到這個預設檔案上,一切就迎刃而解了。實際上Def

(5)ASP.NET Core 中的靜態檔案

1.前言 當我們建立Core專案的時候,Web根目錄下會有個wwwroot檔案目錄,wwwroot檔案目錄裡面預設有HTML、CSS、IMG、JavaScript等檔案,而這些檔案都是Core提供給客戶端使用的靜態檔案。但是這些靜態檔案需要在Core裡面配置才可以對外公開訪問。 2.設定靜態檔案目錄 靜

asp.net core 系列之靜態檔案

這篇講解asp.net core中的靜態檔案(大致翻譯於官網)。 靜態檔案,例如HTML,CSS, images和JavaScript. 要想直接被客戶端訪問,需要做一些配置。 一.Serve static files(提供靜態檔案服務) 靜態檔案儲存在專案的web root 目錄下。預設的目錄是<

Asp.Net Core入門之靜態檔案

靜態檔案(css,js,html等型別檔案)通常位於 web根目錄下,而ASP.Net Core框架預設內容根目錄下的wwwroot資料夾為web根目錄。這裡簡單解釋下內容根目錄:實際就是指包含可執行程式exe,程式集dll,配置檔案json,xml等的檔案目錄. 1.訪問web根目錄靜態檔案 正常

ASP.NET Core on K8S深入學習(3-2)DaemonSetJob

本篇已加入《.NET Core on K8S學習實踐系列文章索引》,可以點選檢視更多容器化技術相關係列文章。 上一篇《3-1 Deployment》中介紹了Deployment,它可以滿足我們大部分時候的應用部署(無狀態服務類容器),但是針對一些特殊的場景應用,就可以用到今天介紹的DaemonSet和Job

15.ASP.NET Core 應用程式中的靜態檔案中介軟體

在這篇文章中,我將向大家介紹,如何使用中介軟體元件來處理靜態檔案。這篇文章中,我們討論下面幾個問題:在ASP.NET Core中,我們需要把靜態檔案存放在哪裡?在ASP.NET Core中 wwwroot資料夾是啥?怎樣在ASP.NET Core應用程式中,配置靜態檔案中介軟體?UseFileServer中介

ASP.NET Core靜態檔案中介軟體[2]: 條件請求以提升效能

通過呼叫IApplicationBuilder介面的UseStaticFiles擴充套件方法註冊的StaticFileMiddleware中介軟體旨在處理針對檔案的請求。對於StaticFileMiddleware中介軟體處理請求的邏輯,大部分讀者都應該想得到:根據請求的地址找到目標檔案的路徑,然後利用註冊的

ASP.NET Core應用的錯誤處理[4]:StatusCodePagesMiddleware中介軟體如何針對響應碼呈現錯誤頁面

StatusCodePagesMiddleware中介軟體與ExceptionHandlerMiddleware中介軟體比較類似,它們都是在後續請求處理過程中“出錯”的情況下利用一個錯誤處理器來完成最終的請求處理與響應的任務。它們之間的差異在於對“錯誤”的界定上,對於ExceptionHandlerMiddl

Jexus針對Asp.net core應用程式的六大不可替代的優勢

3,高效能:Jexus本身是一款與nginx效能相當的高效能Web伺服器,而Jexus與Asp.net core之間,是TCP轉發,不是反向代理之類的HTTP轉發,沒有Http協議解析和重組的效能消耗,因此,Jexus能更好的呈現Asp.net Core的高效能優勢;

ASP.NET Core WebAPI 開啟靜態網頁,設定主頁,跨域,Json保持原始大小寫,新增MIME,解除大檔案上傳限制

開啟靜態網頁 Startup.Configure: app.UseStaticFiles(); 設定主頁 Startup.Configure: DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions();

ASP.NET Core應用基本程式設計模式[1]:管道式的請求處理

HTTP協議自身的特性決定了任何一個Web應用的工作模式都是監聽、接收並處理HTTP請求,並且最終對請求予以響應。HTTP請求處理是管道式設計典型的應用場景:可以根據具體的需求構建一個管道,接收的HTTP請求像水一樣流入這個管道,組成這個管道的各個環節依次對其做相應的處理。雖然ASP.NET Core的請求處

Linux使用Jexus托管Asp.Net Core應用程序

技術 文件目錄 只需要 true 沒有 repr tag 博文 env 第一步 安裝.Net Core環境 安裝 dotnet 環境參見官方網站 https://www.microsoft.com/net/core。 選擇對應的系統版本進行安裝。安裝完成過後 輸入命令查

在 Azure WebApps 中運行64位 Asp.net Core 應用

需求 正常 mmu www. module .config 正在 external doc 作為微軟下一代的開源的跨平臺的開發框架, Asp.net core 正在吸引越來越多的開發者基於其構建現代 web 應用。 目前, Azure App Service 也實現了對 a

運行Vue在ASP.NET Core應用程序並部署在IIS上

生產環境 所在 來講 一個 重寫 文章 .net core 設置 分享 前言 從.NET Core 1.0開始我們就將其應用到項目中,但是呢我對ASP.NET Core一些原理也還未開始研究,僅限於會用,不過園子中已有大量文章存在,借著有點空余時間,我們來講講如何利用AS

ASP.NET Core應用程序部署至生產環境中(CentOS7)

for linux home web 虛擬 direct director block bic 閱讀目錄 環境說明 準備你的ASP.NET Core應用程序 安裝CentOS7 安裝.NET Core SDK for CentOS7。 部署ASP.NET

使用Docker部署ASP.NET Core應用程序實踐

4.0 cor run .com cnblogs pda word 本地配置 問題 前言 最近把很火的Docker給看了,於是就磨拳擦掌要去實踐一下。於是就拿之前一個aps.net core的項目(已被停止)去練手。該項目之前在ubuntu14.04上確保可以正常運行,所以