精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

為什么 HTTP 請求會返回 304?

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
本文阿寶哥基于 Koa 的緩存示例,介紹了 HTTP 304 狀態(tài)碼和 fresh 模塊中的 fresh 函數(shù)是如何實(shí)現(xiàn)資源新鮮度檢測的。希望閱讀完本文后,你對 HTTP 和瀏覽器的緩存機(jī)制有更深入的理解。

[[402402]]

相信大多數(shù) Web 開發(fā)者,對 HTTP 304 狀態(tài)碼都不會陌生。本文阿寶哥將基于 Koa 緩存的示例,為大家介紹 HTTP 304 狀態(tài)碼和 fresh 模塊中的 fresh 函數(shù)是如何實(shí)現(xiàn)資源新鮮度檢測的。如果你對瀏覽器的緩存機(jī)制還不了解的話,建議你先閱讀 深入理解瀏覽器的緩存機(jī)制 這篇文章。

一、304 狀態(tài)碼

在 HTTP 中的 ETag 是如何生成的? 這篇文章中,介紹了 ETag 是如何生成的。在 ETag 實(shí)戰(zhàn)環(huán)節(jié),阿寶哥基于 koa、koa-conditional-get、koa-etag 和 koa-static 這些庫,演示了在實(shí)際項(xiàng)目中如何利用 ETag 響應(yīng)頭和 If-None-Match 請求頭實(shí)現(xiàn)資源的緩存控制。

  1. // server.js 
  2. const Koa = require("koa"); 
  3. const path = require("path"); 
  4. const serve = require("koa-static"); 
  5. const etag = require("koa-etag"); 
  6. const conditional = require("koa-conditional-get"); 
  7.  
  8. const app = new Koa(); 
  9.  
  10. app.use(conditional()); // 使用條件請求中間件 
  11. app.use(etag()); // 使用etag中間件 
  12. app.use( // 使用靜態(tài)資源中間件 
  13.   serve(path.join(__dirname, "/public"), { 
  14.     maxage: 10 * 1000, // 設(shè)置緩存存儲的最大周期,單位為秒 
  15.   }); 
  16. ); 
  17.  
  18. app.listen(3000, () => { 
  19.   console.log("app starting at port 3000"); 
  20. }); 

在啟動完服務(wù)器之后,我們打開 Chrome 開發(fā)者工具并切換到 Network 標(biāo)簽欄,然后在瀏覽器地址欄輸入 http://localhost:3000/ 地址,接著多次訪問該地址(地址欄多次回車)。

上圖是阿寶哥多次訪問的結(jié)果,在圖中我們可以看到 200 和 304 狀態(tài)碼。其中 304 狀態(tài)碼表示資源在由請求頭中的 If-Modified-Since 或 If-None-Match 參數(shù)指定的這一版本之后,未曾被修改。在這種情況下,由于客戶端仍然具有以前下載的副本,因此不需要重新傳輸資源。

下面我們以 index.js 資源為例,來近距離觀察一下 304 響應(yīng)報(bào)文:

  1. HTTP/1.1 304 Not Modified 
  2. Last-Modified: Sat, 29 May 2021 02:24:53 GMT 
  3. Cache-Control: max-age=10 
  4. ETag: W/"29-179b5f04654" 
  5. Date: Sat, 29 May 2021 02:25:26 GMT 
  6. Connection: keep-alive 

對于以上的響應(yīng)報(bào)文,在響應(yīng)頭中包含了 Last-Modified、Cache-Control 和 ETag 這些與緩存相關(guān)的字段。如果你對這些字段的作用還不熟悉的話,可以閱讀 深入理解瀏覽器的緩存機(jī)制 和 HTTP 中的 ETag 是如何生成的? 這兩篇文章。接下來,阿寶哥將跟大家一起來探索一下為什么 10s 后,請求 index.js 資源會返回 304 ?

二、為何返回 304 狀態(tài)碼

在前面的示例中,我們通過使用 app.use 方法注冊了 3 個中間件:

  1. app.use(conditional()); // 使用條件請求中間件 
  2. app.use(etag()); // 使用etag中間件 
  3. app.use( // 使用靜態(tài)資源中間件 
  4.   serve(path.join(__dirname, "/public"), { 
  5.     maxage: 10 * 1000, // 設(shè)置緩存存儲的最大周期,單位為秒 
  6.   }) 
  7. ); 

首先注冊的是 koa-conditional-get 中間件,該中間件用于處理 HTTP 條件請求。在這類請求中,請求的結(jié)果,甚至請求成功的狀態(tài),都會隨著驗(yàn)證器與受影響資源的比較結(jié)果的變化而變化。HTTP 條件請求可以用來驗(yàn)證緩存的有效性,省去不必要的控制手段。

其實(shí) koa-conditional-get 中間件的實(shí)現(xiàn)很簡單,具體如下所示:

  1. // https://github.com/koajs/conditional-get/blob/master/index.js 
  2. module.exports = function conditional () { 
  3.   return async function (ctx, next) { 
  4.     await next() 
  5.     if (ctx.fresh) { 
  6.       ctx.status = 304 
  7.       ctx.body = null 
  8.     } 
  9.   } 

由以上代碼可知,當(dāng)請求上下文對象的 fresh 屬性為 true 時(shí),就會設(shè)置響應(yīng)的狀態(tài)碼為 304。因此,接下來我們的重點(diǎn)就是分析 ctx.fresh 值的設(shè)置條件。

通過閱讀 koa/lib/context.js 文件的源碼,我們可知當(dāng)訪問上下文對象的 fresh 屬性時(shí),實(shí)際上是訪問 request 對象的 fresh 屬性。

  1. // 代理request對象 
  2. delegate(proto, 'request'
  3.    // 省略其它代理 
  4.   .getter('fresh'
  5.   .getter('ips'
  6.   .getter('ip'); 

而 request 對象上的 fresh 屬性是通過 getter 方式來定義的,具體如下所示:

  1. // node_modules/koa/lib/request.js 
  2. module.exports = { 
  3.   // 省略部分代碼 
  4.   get fresh() { 
  5.     const method = this.method; // 獲取請求方法 
  6.     const s = this.ctx.status; // 獲取狀態(tài)碼 
  7.  
  8.     if ('GET' !== method && 'HEAD' !== method) return false
  9.  
  10.     // 2xx or 304 as per rfc2616 14.26 
  11.     if ((s >= 200 && s < 300) || 304 === s) { 
  12.       return fresh(this.header, this.response.header); 
  13.     } 
  14.     return false
  15.   }, 

method && 'HEAD' !== method) return false; // 2xx or 304 as per rfc2616 14.26 if ((s >= 200 && s < 300) || 304 === s) { return fresh(this.header, this.response.header); } return false; },}

在 fresh 方法中,僅當(dāng)請求為 GET/HEAD 請求且狀態(tài)碼為 2xx 或 304 才會執(zhí)行新鮮度檢測。而對應(yīng)的新鮮度檢測邏輯被封裝在 fresh 模塊中,所以接下來我們來分析該模塊是如何檢測新鮮度?

三、如何檢測新鮮度

fresh 模塊對外提供了 fresh 函數(shù),該函數(shù)支持 2 個參數(shù):reqHeaders 和 resHeaders。在該函數(shù)內(nèi)部,新鮮度檢測的邏輯可以分為以下 4 個部分:

3.1 判斷是否條件請求

  1. // https://github.com/jshttp/fresh/blob/master/index.js 
  2. function fresh (reqHeaders, resHeaders) { 
  3.   var modifiedSince = reqHeaders['if-modified-since']  
  4.   var noneMatch = reqHeaders['if-none-match'
  5.  
  6.   // 非條件請求 
  7.   if (!modifiedSince && !noneMatch) { 
  8.     return false 
  9.   } 

如果請求頭未包含 if-modified-since 和 if-none-match 字段,則直接返回 false。

3.2 判斷 cache-control 請求頭

  1. // https://github.com/jshttp/fresh/blob/master/index.js 
  2. var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/ 
  3.  
  4. function fresh (reqHeaders, resHeaders) { 
  5.   var modifiedSince = reqHeaders['if-modified-since']  
  6.   var noneMatch = reqHeaders['if-none-match'
  7.    
  8.   // Always return stale when Cache-Control: no-cache 
  9.   // to support end-to-end reload requests 
  10.   // https://tools.ietf.org/html/rfc2616#section-14.9.4 
  11.   var cacheControl = reqHeaders['cache-control'
  12.   if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) { 
  13.     return false 
  14.   } 

當(dāng) cache-control 請求頭的值為 no-cache 時(shí),則返回 false,以支持端到端的重載請求。需要注意的是,no-cache 并不是表示不緩存,而是表示資源被緩存,但是立即失效,下次會發(fā)起請求驗(yàn)證資源是否過期。 如果你不緩存任何響應(yīng),需要設(shè)置 cache-control 的值為 no-store。

3.3 檢測 ETag 是否匹配

  1. // https://github.com/jshttp/fresh/blob/master/index.js 
  2. function fresh (reqHeaders, resHeaders) { 
  3.   var modifiedSince = reqHeaders['if-modified-since']  
  4.   var noneMatch = reqHeaders['if-none-match'
  5.    
  6.   // 省略部分代碼 
  7.   if (noneMatch && noneMatch !== '*') { 
  8.     var etag = resHeaders['etag'] // 獲取響應(yīng)頭中的etag字段的值 
  9.  
  10.     if (!etag) { // 響應(yīng)頭未設(shè)置etag,則直接返回false 
  11.       return false 
  12.     } 
  13.  
  14.     var etagStale = true // stale:不新鮮 
  15.     var matches = parseTokenList(noneMatch) // 解析noneMatch 
  16.     for (var i = 0; i < matches.length; i++) { // 執(zhí)行循環(huán)匹配操作 
  17.       var match = matches[i] 
  18.       if (match === etag || match === 'W/' + etag || 'W/' + match === etag) { 
  19.         etagStale = false 
  20.         break 
  21.       } 
  22.     } 
  23.  
  24.     if (etagStale) { 
  25.       return false 
  26.     } 
  27.   } 
  28.   return true 

在以上代碼中 parseTokenList 函數(shù)的作用,是為了處理 'if-none-match': ' "bar" , "foo"' 這種情形。在解析的過程中,會去掉多余的空格,并且還會拆分使用逗號分隔符做分隔的 etag 值。而執(zhí)行循環(huán)匹配的目的,也是為了支持以下測試用例:

  1. // https://github.com/jshttp/fresh/blob/master/test/fresh.js     
  2. describe('when at least one matches'function () { 
  3.   it('should be fresh'function () { 
  4.     var reqHeaders = { 'if-none-match'' "bar" , "foo"' } 
  5.     var resHeaders = { 'etag''"foo"' } 
  6.     assert.ok(fresh(reqHeaders, resHeaders)) 
  7.    }) 
  8. }) 

此外,以上代碼中的 W/(大小寫敏感) 表示使用弱驗(yàn)證器。弱驗(yàn)證器很容易生成,但不利于比較。而如果 etag 中不包含 W/,則表示強(qiáng)驗(yàn)證器,它是比較理想的選擇,但很難有效地生成。相同資源的兩個弱 etag 值可能語義等同,但不是每個字節(jié)都相同。

3.4 判斷 Last-Modified 是否過期

  1. // https://github.com/jshttp/fresh/blob/master/index.js 
  2. function fresh (reqHeaders, resHeaders) { 
  3.   var modifiedSince = reqHeaders['if-modified-since'] // 獲取請求頭中的修改時(shí)間 
  4.   var noneMatch = reqHeaders['if-none-match'
  5.  
  6.   // if-modified-since 
  7.   if (modifiedSince) { 
  8.     var lastModified = resHeaders['last-modified'] // 獲取響應(yīng)頭中的修改時(shí)間 
  9.     var modifiedStale = !lastModified || !(parseHttpDate(lastModified) <= parseHttpDate(modifiedSince)) 
  10.  
  11.     if (modifiedStale) { 
  12.       return false 
  13.     } 
  14.   } 
  15.  
  16.   return true 

Last-Modified 的判斷邏輯很簡單,當(dāng)響應(yīng)頭未設(shè)置 last-modified 字段信息或者響應(yīng)頭中 last-modified 的值大于請求頭 if-modified-since 字段對應(yīng)的修改時(shí)間時(shí),則新鮮度的檢測結(jié)果為 false,即表示資源已被修改過,已經(jīng)不新鮮了。

了解完 fresh 函數(shù)的具體實(shí)現(xiàn)之后,我們再來回顧一下 Last-Modified 和 ETag 之間的區(qū)別:

  • 精確度上,Etag 要優(yōu)于 Last-Modified。Last-Modified 的時(shí)間單位是秒,如果某個文件在 1 秒內(nèi)被改變多次,那么它們的 Last-Modified 并沒有體現(xiàn)出來修改,但是 Etag 每次都會改變,從而確保了精度;此外,如果是負(fù)載均衡的服務(wù)器,各個服務(wù)器生成的 Last-Modified 也有可能不一致。
  • 性能上,Etag 要遜于 Last-Modified,畢竟 Last-Modified 只需要記錄時(shí)間,而 ETag 需要服務(wù)器通過消息摘要算法來計(jì)算出一個hash 值。
  • 優(yōu)先級上,在資源新鮮度校驗(yàn)時(shí),服務(wù)器會優(yōu)先考慮 Etag。 即如果條件請求的請求頭同時(shí)攜帶 If-Modified-Since 和 If-None-Match 字段,則會優(yōu)先判斷資源的 ETag 值是否發(fā)生變化。

看到這里相信你對示例中 index.js 資源請求返回 304 的原因,應(yīng)該有了大致的理解。如果你對 koa-etag 中間件是如何生成 ETag 感興趣的話,可以閱讀 HTTP 中的 ETag 是如何生成的? 這篇文章。

四、緩存機(jī)制

強(qiáng)緩存優(yōu)先于協(xié)商緩存進(jìn)行,若強(qiáng)緩存(Expires 和 Cache-Control)生效則直接使用緩存,若不生效則進(jìn)行協(xié)商緩存(Last-Modified/If-Modified-Since 和 Etag/If-None-Match),協(xié)商緩存由服務(wù)器決定是否使用緩存,若協(xié)商緩存失效,那么代表該請求的緩存失效,返回 200,重新返回資源和緩存標(biāo)識,再存入瀏覽器緩存中;生效則返回 304,繼續(xù)使用緩存。

具體的緩存機(jī)制如下圖所示:

為了讓大家能夠更好地理解緩存機(jī)制,我們再來簡單分析一下前面的介紹 Koa 緩存示例:

  1. // server.js 
  2. const Koa = require("koa"); 
  3. const path = require("path"); 
  4. const serve = require("koa-static"); 
  5. const etag = require("koa-etag"); 
  6. const conditional = require("koa-conditional-get"); 
  7.  
  8. const app = new Koa(); 
  9.  
  10. app.use(conditional()); // 使用條件請求中間件 
  11. app.use(etag()); // 使用etag中間件 
  12. app.use( // 使用靜態(tài)資源中間件 
  13.   serve(path.join(__dirname, "/public"), { 
  14.     maxage: 10 * 1000, // 設(shè)置緩存存儲的最大周期,單位為秒 
  15.   }); 
  16. ); 
  17.  
  18. app.listen(3000, () => { 
  19.   console.log("app starting at port 3000"); 
  20. }); 

以上示例使用了 koa-conditional-get、koa-etag 和 koa-static 這 3 個中間件。它們的具體定義分別如下:

4.1 koa-conditional-get

  1. // https://github.com/koajs/conditional-get/blob/master/index.js 
  2. module.exports = function conditional () { 
  3.   return async function (ctx, next) { 
  4.     await next() 
  5.     if (ctx.fresh) { // 資源未更新,則返回304 Not Modified  
  6.       ctx.status = 304 
  7.       ctx.body = null 
  8.     } 
  9.   } 

koa-conditional-get 中間件的實(shí)現(xiàn)很簡單,如果資源是新鮮的,則直接返回 304 狀態(tài)碼并設(shè)置響應(yīng)體為 null。

4.2 koa-etag

  1. // https://github.com/koajs/etag/blob/master/index.js 
  2. module.exports = function etag (options) { 
  3.   return async function etag (ctx, next) { 
  4.     await next() 
  5.     const entity = await getResponseEntity(ctx) // 獲取響應(yīng)實(shí)體對象 
  6.     setEtag(ctx, entity, options) 
  7.   } 

在 koa-etag 中間件內(nèi)部,當(dāng)獲取到響應(yīng)實(shí)體對象之后,會調(diào)用 setEtag 函數(shù)來設(shè)置 ETag。setEtag 函數(shù)的定義如下:

  1. // https://github.com/koajs/etag/blob/master/index.js 
  2. const calculate = require('etag'
  3.  
  4. function setEtag (ctx, entity, options) { 
  5.   if (!entity) return 
  6.   ctx.response.etag = calculate(entity, options) 

很明顯在 koa-etag 中間件內(nèi)部是通過 etag 這個庫,來為響應(yīng)實(shí)體生成對應(yīng)的 etag的。

4.3 koa-static

  1. // https://github.com/koajs/static/blob/master/index.js 
  2. function serve (root, opts) { 
  3.   opts = Object.assign(Object.create(null), opts) 
  4.   // 省略部分代碼 
  5.   return async function serve (ctx, next) { 
  6.     await next() 
  7.     if (ctx.method !== 'HEAD' && ctx.method !== 'GET'return 
  8.     // response is already handled 
  9.     if (ctx.body != null || ctx.status !== 404) return 
  10.     try { 
  11.       await send(ctx, ctx.path, opts) 
  12.     } catch (err) { 
  13.       if (err.status !== 404) { 
  14.         throw err 
  15.       } 
  16.     } 
  17.   } 

對于 koa-static 中間件來說,當(dāng)請求方法不是 GET 或 HEAD 請求(不應(yīng)包含響應(yīng)體)時(shí),則直接返回。而靜態(tài)資源的處理能力,實(shí)際是交由 send 這個庫來實(shí)現(xiàn)的。

最后為了讓小伙伴們能夠更好地理解以上中間件的處理邏輯,阿寶哥帶大家來簡單回顧一下洋蔥模型:

在上圖中,洋蔥內(nèi)的每一層都表示一個獨(dú)立的中間件,用于實(shí)現(xiàn)不同的功能,比如異常處理、緩存處理等。每次請求都會從左側(cè)開始一層層地經(jīng)過每層的中間件,當(dāng)進(jìn)入到最里層的中間件之后,就會從最里層的中間件開始逐層返回。因此對于每層的中間件來說,在一個 請求和響應(yīng) 周期中,都有兩個時(shí)機(jī)點(diǎn)來添加不同的處理邏輯。

五、總結(jié)

本文阿寶哥基于 Koa 的緩存示例,介紹了 HTTP 304 狀態(tài)碼和 fresh 模塊中的 fresh 函數(shù)是如何實(shí)現(xiàn)資源新鮮度檢測的。希望閱讀完本文后,你對 HTTP 和瀏覽器的緩存機(jī)制有更深入的理解。此外,本文只是簡單介紹了 Koa 的洋蔥模型,如果你對洋蔥模型感興趣,可以繼續(xù)閱 如何更好地理解中間件和洋蔥模型 這篇文章。

六、參考資源

  • MDN - HTTP 條件請求
  • HTTP 中的 ETag 是如何生成的?

 

責(zé)任編輯:姜華 來源: 全棧修仙之路
相關(guān)推薦

2022-03-30 08:21:57

合并HTTP

2024-12-26 09:05:18

HTTP狀態(tài)碼數(shù)據(jù)

2020-08-16 11:29:12

Python函數(shù)開發(fā)

2020-10-12 14:31:16

HTTP之200還是3

2022-05-30 10:23:59

HTTPHTTP 1.1TCP

2021-10-30 19:57:00

HTTP2 HTTP

2021-06-02 10:52:01

HTTP3Linux

2012-08-17 10:01:07

云計(jì)算

2020-03-30 15:05:46

Kafka消息數(shù)據(jù)

2012-03-26 10:26:43

openstackeucalyptus

2021-07-09 09:24:06

NanoID UUID軟件開發(fā)

2012-05-02 10:08:51

桌面Linux微軟

2022-04-13 20:53:15

Spring事務(wù)管理

2021-01-25 07:14:53

Cloud DevOps云計(jì)算

2023-03-22 09:10:18

IT文檔語言

2014-03-05 14:58:00

蘋果CarPlayiOS

2015-12-07 10:49:43

卸載App用戶體驗(yàn)

2022-05-11 08:22:54

IO負(fù)載NFSOS

2019-04-24 08:00:00

HTTPSHTTP前端

2022-06-07 08:39:35

RPCHTTP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

免费观看黄色大片| 欧亚精品在线观看| 潘金莲一级淫片aaaaa| 丁香花在线影院| 成人亚洲精品久久久久软件| 68精品久久久久久欧美| 内射毛片内射国产夫妻| 麻豆久久一区| 色哟哟国产精品免费观看| 亚洲一区二区在线看| 亚洲精品无amm毛片| 裸体一区二区| 欧美猛男性生活免费| 三上悠亚ssⅰn939无码播放 | 欧美激情精品久久久久| 欧美成人国产精品一区二区| 午夜久久av| 91国产视频在线观看| 超碰人人爱人人| 2017亚洲天堂1024| 99久久综合精品| 91香蕉亚洲精品| 欧美一区免费看| 激情欧美亚洲| 欧美精品午夜视频| 黄色av片三级三级三级免费看| 国产精品主播在线观看| 欧美精选一区二区| 99蜜桃臀久久久欧美精品网站| 91精品国产91久久久久久青草| 国产午夜亚洲精品羞羞网站| 国产一级特黄a大片99| 国产美女自慰在线观看| 久久久蜜桃一区二区人| 国语自产在线不卡| 欧美三级 欧美一级| 欧美三级情趣内衣| 亚洲老板91色精品久久| 亚洲午夜久久久久久久久| 中文字幕日韩亚洲| 欧美日韩亚洲不卡| 欧美日韩在线视频一区二区三区| 性欧美videoshd高清| 亚洲欧洲精品天堂一级| 日韩中文一区二区三区| 国产在线中文字幕| 久久人人爽人人爽| 蜜桃av色综合| 欧美zozo| 2024国产精品视频| 美女一区视频| 黄色软件在线观看| 国产午夜精品理论片a级大结局| 精品一区二区三区自拍图片区| 免费看黄网站在线观看| 成人免费va视频| 国产在线一区二区三区四区| 亚洲精品成人电影| 成人看片黄a免费看在线| 99免费在线观看视频| 成 人 免费 黄 色| 成人亚洲精品久久久久软件| 国产一区精品在线| 日本亚洲一区| 久久久91精品国产一区二区精品 | 欧美综合视频| 日韩天堂在线视频| 亚洲xxxx3d动漫| 亚洲第一偷拍| 久久久免费av| 久久久久久不卡| 日本vs亚洲vs韩国一区三区| 国产在线观看一区二区三区 | 99久久精品国产毛片| 久久av二区| 国产中文字幕在线播放| 亚洲欧洲一区二区在线播放| 97中文字幕在线| 蜜桃视频在线网站| 在线视频综合导航| 婷婷激情5月天| av日韩在线播放| 亚洲男女自偷自拍图片另类| 激情五月激情综合| 国语精品一区| 日韩av片永久免费网站| 国产精品人人爽| 不卡的电视剧免费网站有什么| 久久久水蜜桃| 欧美性天天影视| 午夜久久福利影院| www.精品在线| youjizzjizz亚洲| 国产午夜精品美女视频明星a级| 美女视频久久久| 亚洲国产裸拍裸体视频在线观看乱了中文| 51久久精品夜色国产麻豆| 在线观看亚洲一区二区| 成人一级视频在线观看| 日韩欧美视频一区二区三区四区| 成人日韩欧美| 欧美日韩激情小视频| 国产美女视频免费看| 欧美男人操女人视频| 亚洲精品97久久| 久久精品国产亚洲av久| 欧美日本三区| 国产精品一区二区3区| 色欲av伊人久久大香线蕉影院| 亚洲国产高清在线观看视频| 黄色三级中文字幕| 久久国产三级| 亚洲男人天堂网站| 精品少妇久久久| 久久er精品视频| 欧美一区二区高清在线观看| 蜜臀av在线播放| 欧美丰满一区二区免费视频| 瑟瑟视频在线观看| 好吊日精品视频| 91性高湖久久久久久久久_久久99| 日韩欧美在线番号| 亚洲精品欧美综合四区| 成人性生交免费看| 久久av综合| 97香蕉超级碰碰久久免费软件 | 性生交大片免费全黄| 日韩精品视频网| 久久久久久国产精品mv| 国内老司机av在线| 日韩欧美国产精品| 久艹在线观看视频| 久久er99热精品一区二区| 偷拍视频一区二区| 日韩精品免费观看视频| 亚洲男人的天堂网站| 日韩视频在线观看一区| 处破女av一区二区| 17c丨国产丨精品视频| 国产在线|日韩| 国产亚洲精品美女久久久久| 中文字幕在线播| 91蜜桃免费观看视频| 3d动漫一区二区三区| 99精品国产高清一区二区麻豆| 欧美久久精品午夜青青大伊人| 97人妻精品一区二区三区软件| 中文字幕成人在线观看| 婷婷免费在线观看| 久久综合av| 亚洲一区二区三区四区在线播放| 欧美69xxxx| 777色狠狠一区二区三区| 永久av免费网站| 国产麻豆午夜三级精品| 日韩a级黄色片| 精品av导航| 欧美中文字幕第一页| 精品视频一二区| 欧美性xxxxxxxx| 天堂网中文在线观看| 国产精品亚洲一区二区三区妖精 | 国产91精品久久久久久久网曝门| 日韩精品手机在线观看| 综合激情久久| 91成人天堂久久成人| 噜噜噜在线观看播放视频| 91久久精品日日躁夜夜躁欧美| 成人性生交大片免费看无遮挡aⅴ| 欧美aa在线视频| 欧美美女直播网站| 亚洲精品影院| 国产午夜精品一区在线观看| 久久99热精品| 香蕉视频黄色片| 欧美性猛片aaaaaaa做受| 强制高潮抽搐sm调教高h| 国产成人精品亚洲午夜麻豆| 国产午夜大地久久| 精品少妇av| 99精彩视频在线观看免费| 国产99在线观看| 伊人一区二区三区久久精品| 国产成人麻豆精品午夜在线| 亚洲国产sm捆绑调教视频| 日本少妇高潮喷水xxxxxxx| 激情六月婷婷久久| av日韩一区二区三区| 欧美手机视频| 国产乱子伦精品| 国产a亚洲精品| 久久人91精品久久久久久不卡| 久久伊伊香蕉| 日韩欧美一级精品久久| 亚洲欧美偷拍一区| 亚洲欧美经典视频| 国产成人精品无码免费看夜聊软件| 国精产品一区一区三区mba视频| av日韩一区二区三区| 欧美gayvideo| 蜜桃视频在线观看成人| 国产一区二区三区| 国产成人啪精品视频免费网| 丝袜在线观看| 中文字幕av一区中文字幕天堂 | 88久久精品| 国产精品久久久久久亚洲调教| 欧美日韩色网| 俺去了亚洲欧美日韩| 色视频在线看| 精品国产乱码久久久久久蜜臀| 亚洲一卡二卡在线| 欧美性黄网官网| 久久精品www| 中文字幕日韩一区| 受虐m奴xxx在线观看| 成人免费视频国产在线观看| 亚洲精品综合在线观看| 久久一二三四| 日韩少妇内射免费播放| 国产一区日韩一区| 色撸撸在线观看| 国产欧美日韩精品一区二区免费| 国产精品美女xx| 欧美精品三级在线| 91精品视频在线免费观看| 日韩一区二区三区在线免费观看| 午夜精品视频在线| 青青青国内视频在线观看软件| 日日噜噜噜夜夜爽亚洲精品 | 亚欧日韩另类中文欧美| 成人h视频在线观看| 亚洲a成人v| 国产日韩专区在线| 色综合天天色| 国产精品色悠悠| 精品欧美日韩精品| 国产精品久久久久久久久久| 在线观看欧美日韩电影| 7777kkkk成人观看| 天堂网在线最新版www中文网| 久久久之久亚州精品露出| 污污片在线免费视频| 美日韩精品免费视频| 永久免费网站在线| 欧美大片在线影院| 日韩专区av| 欧美黑人性视频| 波多野结衣中文在线| 97精品一区二区视频在线观看| 国产传媒在线| 欧美最顶级的aⅴ艳星| 制服诱惑亚洲| 国产精品久久久久久久美男| 欧美激情啪啪| 91理论片午午论夜理片久久| 国内精品视频| 俄罗斯精品一区二区| 久久91在线| 秋霞在线观看一区二区三区| 欧美日韩水蜜桃| 影音欧美亚洲| 狠狠综合久久av一区二区老牛| 亚洲精品蜜桃久久久久久| 亚洲高清不卡| 欧美激情精品久久久久久小说| 奇米一区二区三区av| 国产精品嫩草影院8vv8 | 欧美性感一类影片在线播放| 97人人爽人人爽人人爽| 日韩视频在线一区二区| 日本人妻丰满熟妇久久久久久| 亚洲精品小视频| av资源网站在线观看| 久久综合免费视频| free性m.freesex欧美| 国产成人精品一区二区在线| 亚洲欧洲二区| 国产亚洲一区在线播放| 日韩伦理一区| 日韩亚洲欧美视频| 日韩成人av影视| 潘金莲一级淫片aaaaa| 久久久久综合网| 成熟的女同志hd| 色婷婷av一区二区三区gif| 97人妻一区二区精品免费视频| 亚洲国产精品成人va在线观看| 成年人在线看| 欧美极品欧美精品欧美视频 | 在线日韩影院| 91久久久久久久久久久| 欧美爱爱网站| 免费在线观看污污视频| 国产精品亚洲综合久久| 中文字幕12页| 久久久久国产一区二区三区四区 | 91丝袜脚交足在线播放| 免费精品国产| 日韩精品一区二区免费| 蜜桃av一区二区在线观看| 日韩无码精品一区二区| 国产精品夫妻自拍| 韩国av中文字幕| 日韩一区二区三区在线视频| 国产免费av高清在线| 久久久久久久国产精品| 欧美日韩伦理一区二区| 久久亚洲午夜电影| 国语自产精品视频在线看8查询8| 黄大色黄女片18第一次| 久久午夜色播影院免费高清| 免费在线黄色片| 欧美日韩成人一区| 免费国产在线视频| 亚洲91精品在线| 日韩一区网站| 天堂v在线视频| 美女视频黄频大全不卡视频在线播放| 男男做爰猛烈叫床爽爽小说| 一区二区三区在线影院| 91久久精品无码一区二区| 亚洲三级黄色在线观看| 久草在线中文最新视频| 国产精品青青草| 欧美精品偷拍| 国产又粗又猛又爽又黄| 中文字幕一区二区在线观看| 午夜一区二区三区四区| 亚洲欧美在线一区| 最新欧美色图| 免费中文日韩| 欧美一级久久| 五月婷婷综合在线观看| 精品成人乱色一区二区| 日韩一卡二卡在线| 欧美极品少妇xxxxx| 亚洲91网站| 女人床在线观看| 国产乱对白刺激视频不卡| 久久国产波多野结衣| 69p69国产精品| 国产鲁鲁视频在线观看特色| 成人黄色中文字幕| 久久久久电影| 亚洲国产欧美91| 一二三区精品视频| 亚洲欧美另类视频| 国语对白做受69| 妖精视频一区二区三区| 国产免费视频传媒| 中文字幕亚洲一区二区av在线| 国产一区二区在线视频观看| 久久久精品美女| 亚洲一二av| 国产一区二区网| 久久久久国产精品麻豆| 中文字幕 自拍偷拍| 日韩中文字幕在线| 亚洲天堂av资源在线观看| 欧日韩免费视频| 26uuu久久天堂性欧美| 中文字幕手机在线视频| 最近2019年手机中文字幕| 粉嫩av国产一区二区三区| 久久这里只有精品18| 91免费看`日韩一区二区| 波多野结衣激情视频| 久久精品亚洲热| 极品一区美女高清| 男人搞女人网站| 亚洲精品v日韩精品| 亚洲免费黄色片| 日本精品视频在线| 99久久夜色精品国产亚洲狼| 成人在线观看一区二区| 日韩欧美中文免费| 色影院视频在线| 国产精品免费一区二区三区四区| 美女诱惑一区| 免费在线黄色网| 国产视频亚洲精品| 成人激情久久| 啊啊啊一区二区| 亚洲三级久久久| 日韩二区三区| 91综合免费在线| 蜜桃av综合| 久久99久久98精品免观看软件 | 国产精品yjizz视频网| 日韩在线国产| 不卡的看片网站| 国产精品欧美综合亚洲| 欧美在线视频观看| 亚洲国产精品成人| 亚洲精品成人无码| 欧美videossexotv100| 成人在线视频免费| 久在线观看视频| 一区二区三区久久|