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

手寫Express核心原理,再也不怕面試官問(wèn)我Express原理

開(kāi)發(fā) 前端
我們可以知道,express得到的是一個(gè)方法,然后方法執(zhí)行后得到了app。而app實(shí)際上也是一個(gè)函數(shù),至于為什么會(huì)是函數(shù),我們下面會(huì)揭秘。
本文轉(zhuǎn)載自微信公眾號(hào)「前端陽(yáng)光」,作者事業(yè)有成的張啦啦 。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端陽(yáng)光公眾號(hào)。

一、首先安裝express

二、創(chuàng)建example.js文件

       創(chuàng)建myExpress.js文件

       實(shí)現(xiàn)app.get()方法

       實(shí)現(xiàn)post等其他方法

       實(shí)現(xiàn)app.all方法

       中間件app.use的實(shí)現(xiàn)

       什么是錯(cuò)誤中間件?

       學(xué)習(xí)總結(jié)

一、首先安裝express

  1. npm install express 

安裝express是為了示范。

已經(jīng)把代碼放到github:https://github.com/Sunny-lucking/HowToBuildMyExpress 。可以順手給個(gè)star嗎?謝謝大佬們。

二、創(chuàng)建example.js文件

  1. // example.js 
  2. const express = require('express'
  3. const app = express() 
  4. const port = 3000 
  5.  
  6. app.get('/', (req, res) => { 
  7.   res.send('Hello World!'
  8. }) 
  9.  
  10. app.listen(port, () => { 
  11.   console.log(`Example app listening at http://localhost:${port}`) 
  12. }) 

如代碼所示,執(zhí)行node example.js就運(yùn)行起了一個(gè)服務(wù)器。

如下圖所示,現(xiàn)在我們決定創(chuàng)建一個(gè)屬于我們的express文件,引入的express改成引入我們手寫的express。

好了,現(xiàn)在開(kāi)始實(shí)現(xiàn)我們的express吧!

創(chuàng)建myExpress.js文件

  1. const express = require('express'
  2. const app = express() 

由 這兩句代碼,我們可以知道,express得到的是一個(gè)方法,然后方法執(zhí)行后得到了app。而app實(shí)際上也是一個(gè)函數(shù),至于為什么會(huì)是函數(shù),我們下面會(huì)揭秘。

我們可以初步實(shí)現(xiàn)express如下:

  1. // myExpress.js 
  2. function createApplication() { 
  3.     let app = function (req,res) { 
  4.  
  5.     } 
  6.     return app; 
  7.  
  8. module.exports = createApplication; 

在上面代碼中,發(fā)現(xiàn)app有l(wèi)isten方法。

因此我們可以進(jìn)一步給app添加listen方法:

  1. // myExpress.js 
  2. function createApplication() { 
  3.     let app = function (req,res) { 
  4.  
  5.     } 
  6.     app.listen = function () { 
  7.  
  8.     } 
  9.     return app; 
  10.  
  11. module.exports = createApplication; 

app.listen實(shí)現(xiàn)的是創(chuàng)建一個(gè)服務(wù)器,并且將服務(wù)器綁定到某個(gè)端口運(yùn)行起來(lái)。

因此可以這樣完善listen方法。

  1. // myExpress.js 
  2. let http = require('http'); 
  3. function createApplication() { 
  4.     let app = function (req,res) { 
  5.         res.end('hahha'); 
  6.     } 
  7.     app.listen = function () { 
  8.         let server = http.createServer(app) 
  9.         server.listen(...arguments); 
  10.  
  11.     } 
  12.     return app; 
  13.  
  14. module.exports = createApplication; 

這里可能會(huì)有同學(xué)有所疑問(wèn),為什么 http.createServer(app)這里要傳入app。

其實(shí)我們不傳入app,也就是說(shuō),讓app不是一個(gè)方法,也是可以的。

我們可以改成這樣。

  1. // myExpress.js 
  2. let http = require('http'); 
  3. function createApplication() { 
  4.     let app = {}; 
  5.  
  6.     app.listen = function () { 
  7.         let server = http.createServer(function (req, res) { 
  8.             res.end('hahha'
  9.         }) 
  10.         server.listen(...arguments); 
  11.  
  12.     } 
  13.     return app; 
  14.  
  15. module.exports = createApplication; 

如代碼所示,我們將app改成一個(gè)對(duì)象,也是沒(méi)有問(wèn)題的。

實(shí)現(xiàn)app.get()方法

app.get方法接受兩個(gè)參數(shù),路徑和回調(diào)函數(shù)。

  1. // myExpress.js 
  2. let http = require('http'); 
  3. function createApplication() { 
  4.     let app = {}; 
  5.     app.routes = [] 
  6.     app.get = function (path, handler) { 
  7.         let layer = { 
  8.             method: 'get'
  9.             path, 
  10.             handler 
  11.         } 
  12.         app.routes.push(layer) 
  13.     } 
  14.     app.listen = function () { 
  15.         let server = http.createServer(function (req, res) { 
  16.              
  17.             res.end('hahha'
  18.         }) 
  19.         server.listen(...arguments); 
  20.     } 
  21.     return app; 
  22.  
  23. module.exports = createApplication; 

如上面代碼所示,給app添加了route對(duì)象,然后get方法執(zhí)行的時(shí)候,將接收到的兩個(gè)參數(shù):路徑和方法,包裝成一個(gè)對(duì)象push到routes里了。

可想而知,當(dāng)我們?cè)跒g覽器輸入路徑的時(shí)候,肯定會(huì)執(zhí)行http.createServer里的回調(diào)函數(shù)。

所以,我們需要在這里 獲得瀏覽器的請(qǐng)求路徑。解析得到路徑。

然后遍歷循環(huán)routes,尋找對(duì)應(yīng)的路由,執(zhí)行回調(diào)方法。如下面代碼所示。

  1. // myExpress.js 
  2. let http = require('http'); 
  3. const url  = require('url'); 
  4. function createApplication() { 
  5.     let app = {}; 
  6.     app.routes = [] 
  7.     app.get = function (path, handler) { 
  8.         let layer = { 
  9.             method: 'get'
  10.             path, 
  11.             handler 
  12.         } 
  13.         app.routes.push(layer) 
  14.     } 
  15.     app.listen = function () { 
  16.         let server = http.createServer(function (req, res) { 
  17.             // 取出layer  
  18.             // 1. 獲取請(qǐng)求的方法 
  19.             let m = req.method.toLocaleLowerCase(); 
  20.             let { pathname } = url.parse(req.url, true); 
  21.              
  22.             // 2.找到對(duì)應(yīng)的路由,執(zhí)行回調(diào)方法 
  23.             for (let i = 0 ; i< app.routes.length; i++){ 
  24.                 let {method,path,handler} = app.routes[i] 
  25.                 if (method === m && path === pathname ) { 
  26.                     handler(req,res); 
  27.                 } 
  28.             } 
  29.             res.end('hahha'
  30.         }) 
  31.         server.listen(...arguments); 
  32.     } 
  33.     return app; 
  34.  
  35. module.exports = createApplication; 

運(yùn)行一下代碼。

可見(jiàn)運(yùn)行成功:

實(shí)現(xiàn)post等其他方法。

很簡(jiǎn)單,我們可以直接復(fù)制app.get方法,然后將method的值改成post就好了。

  1. // myExpress.js 
  2. let http = require('http'); 
  3. const url  = require('url'); 
  4. function createApplication() { 
  5.     。。。 
  6.     app.get = function (path, handler) { 
  7.         let layer = { 
  8.             method: 'get'
  9.             path, 
  10.             handler 
  11.         } 
  12.         app.routes.push(layer) 
  13.     } 
  14.     app.post = function (path, handler) { 
  15.         let layer = { 
  16.             method: 'post'
  17.             path, 
  18.             handler 
  19.         } 
  20.         app.routes.push(layer) 
  21.     } 
  22.     。。。 
  23.     return app; 
  24.  
  25. module.exports = createApplication; 

這樣是可以實(shí)現(xiàn),但是除了post和get,還有其他方法啊,難道每一個(gè)我們都要這樣寫嘛?,當(dāng)然不是,有個(gè)很簡(jiǎn)單的方法。

// myExpress.js

  1. function createApplication() { 
  2.     ...  
  3.     http.METHODS.forEach(method => { 
  4.         method = method.toLocaleLowerCase() 
  5.         app[method] = function (path, handler) { 
  6.             let layer = { 
  7.                 method, 
  8.                 path, 
  9.                 handler 
  10.             } 
  11.             app.routes.push(layer) 
  12.         } 
  13.     }); 
  14.     ... 
  15.  
  16. module.exports = createApplication; 

如代碼所示,http.METHODS是一個(gè)方法數(shù)組。如下面所示的數(shù)組:

  1. ["GET","POST","DELETE","PUT"]。 

遍歷方法數(shù)組,就可以實(shí)現(xiàn)所有方法了。

測(cè)試跑了一下,確實(shí)成功。

實(shí)現(xiàn)app.all方法

all表示的是匹配所有的方法,

app.all('/user')表示匹配所有路徑是/user的路由

app.all('*')表示匹配任何路徑 任何方法 的 路由

實(shí)現(xiàn)all方法也非常簡(jiǎn)單,如下代碼所示:

  1. app.all = function (path, handler){ 
  2.         let layer = { 
  3.             method: "all"
  4.             path, 
  5.             handler 
  6.         } 
  7.         app.routes.push(layer) 
  8.     } 

然后只需要續(xù)改下路由器匹配的邏輯,如下代碼所示,只需要修改下判斷。

  1. app.listen = function () { 
  2.     let server = http.createServer(function (req, res) { 
  3.         // 取出layer  
  4.         // 1. 獲取請(qǐng)求的方法 
  5.         let m = req.method.toLocaleLowerCase(); 
  6.         let { pathname } = url.parse(req.url, true); 
  7.  
  8.         // 2.找到對(duì)應(yīng)的路由,執(zhí)行回調(diào)方法 
  9.         for (let i = 0 ; i< app.routes.length; i++){ 
  10.             let {method,path,handler} = app.routes[i] 
  11.             if ((method === m || method === 'all') && (path === pathname || path === "*")) { 
  12.                 handler(req,res); 
  13.             } 
  14.         } 
  15.         console.log(app.routes); 
  16.         res.end('hahha'
  17.     }) 
  18.     server.listen(...arguments); 

可見(jiàn)成功。

中間件app.use的實(shí)現(xiàn)

這個(gè)方法的實(shí)現(xiàn),跟其他方法差不多,如代碼所示。

  1. app.use = function (path, handler) { 
  2.     let layer = { 
  3.         method: "middle"
  4.         path, 
  5.         handler 
  6.     } 
  7.     app.routes.push(layer) 

但問(wèn)題來(lái)了,使用中間件的時(shí)候,我們會(huì)使用next方法,來(lái)讓程序繼續(xù)往下執(zhí)行,那它是怎么執(zhí)行的。

  1. app.use(function (req, res, next) { 
  2.   console.log('Time:'Date.now()); 
  3.   next(); 
  4. }); 

所以我們必須實(shí)現(xiàn)next這個(gè)方法。

其實(shí)可以猜想,next應(yīng)該就是一個(gè)瘋狂調(diào)用自己的方法。也就是遞歸。

而且每遞歸一次,就把被push到routes里的handler拿出來(lái)執(zhí)行。

實(shí)際上,不管是app.use還說(shuō)app.all還是app.get。其實(shí)都是把layer放進(jìn)routes里,然后再統(tǒng)一遍歷routes來(lái)判斷該不該執(zhí)行l(wèi)ayer里的handler方法。可以看下next方法的實(shí)現(xiàn)。

  1. function next() { 
  2.     // 已經(jīng)迭代完整個(gè)數(shù)組,還是沒(méi)有找到匹配的路徑 
  3.     if (index === app.routes.length) return res.end('Cannot find '
  4.     let { method, path, handler } = app.routes[index++] // 每次調(diào)用next就去下一個(gè)layer 
  5.     if (method === 'middle') { // 處理中間件 
  6.         if (path === '/' || path === pathname || pathname.starWidth(path + '/')) { 
  7.             handler(req, res, next
  8.         } else { // 繼續(xù)遍歷 
  9.             next(); 
  10.         } 
  11.     } else { // 處理路由 
  12.         if ((method === m || method === 'all') && (path === pathname || path === "*")) { 
  13.             handler(req, res); 
  14.         } else { 
  15.             next(); 
  16.         } 
  17.     } 

可以看到是遞歸方法的遍歷routes數(shù)組。

而且我們可以發(fā)現(xiàn),如果是使用中間件的話,那么只要path是“/”或者前綴匹配,這個(gè)中間件就會(huì)執(zhí)行。由于handler會(huì)用到參數(shù)req和res。所以這個(gè)next方法要在 listen里面定義。

如下代碼所示:

  1. // myExpress.js 
  2. let http = require('http'); 
  3. const url = require('url'); 
  4. function createApplication() { 
  5.     let app = {}; 
  6.     app.routes = []; 
  7.     let index = 0; 
  8.  
  9.     app.use = function (path, handler) { 
  10.         let layer = { 
  11.             method: "middle"
  12.             path, 
  13.             handler 
  14.         } 
  15.         app.routes.push(layer) 
  16.     } 
  17.     app.all = function (path, handler) { 
  18.         let layer = { 
  19.             method: "all"
  20.             path, 
  21.             handler 
  22.         } 
  23.         app.routes.push(layer) 
  24.     } 
  25.     http.METHODS.forEach(method => { 
  26.         method = method.toLocaleLowerCase() 
  27.         app[method] = function (path, handler) { 
  28.             let layer = { 
  29.                 method, 
  30.                 path, 
  31.                 handler 
  32.             } 
  33.             app.routes.push(layer) 
  34.         } 
  35.     }); 
  36.     app.listen = function () { 
  37.         let server = http.createServer(function (req, res) { 
  38.             // 取出layer  
  39.             // 1. 獲取請(qǐng)求的方法 
  40.             let m = req.method.toLocaleLowerCase(); 
  41.             let { pathname } = url.parse(req.url, true); 
  42.  
  43.             // 2.找到對(duì)應(yīng)的路由,執(zhí)行回調(diào)方法 
  44.             function next() { 
  45.                 // 已經(jīng)迭代完整個(gè)數(shù)組,還是沒(méi)有找到匹配的路徑 
  46.                 if (index === app.routes.length) return res.end('Cannot find '
  47.                 let { method, path, handler } = app.routes[index++] // 每次調(diào)用next就去下一個(gè)layer 
  48.                 if (method === 'middle') { // 處理中間件 
  49.                     if (path === '/' || path === pathname || pathname.starWidth(path + '/')) { 
  50.                         handler(req, res, next
  51.                     } else { // 繼續(xù)遍歷 
  52.                         next(); 
  53.                     } 
  54.                 } else { // 處理路由 
  55.                     if ((method === m || method === 'all') && (path === pathname || path === "*")) { 
  56.                         handler(req, res); 
  57.                     } else { 
  58.                         next(); 
  59.                     } 
  60.                 } 
  61.             } 
  62.  
  63.             next() 
  64.             res.end('hahha'
  65.         }) 
  66.         server.listen(...arguments); 
  67.     } 
  68.     return app; 
  69.  
  70. module.exports = createApplication; 

當(dāng)我們請(qǐng)求路徑就會(huì)發(fā)現(xiàn)中間件確實(shí)執(zhí)行成功。

不過(guò),這里的中間價(jià)實(shí)現(xiàn)還不夠完美。

因?yàn)椋覀兪褂弥虚g件的時(shí)候,是可以不用傳遞路由的。例如:

  1. app.use((req,res) => { 
  2.   console.log("我是沒(méi)有路由的中間價(jià)"); 
  3. }) 

這也是可以使用的,那該怎么實(shí)現(xiàn)呢,其實(shí)非常簡(jiǎn)單,判斷一下有沒(méi)有傳遞路徑就好了,沒(méi)有的話,就給個(gè)默認(rèn)路徑“/”,實(shí)現(xiàn)代碼如下:

  1. app.use = function (path, handler) { 
  2.     if(typeof path !== "string") { // 第一個(gè)參數(shù)不是字符串,說(shuō)明不是路徑,而是方法 
  3.         handler = path; 
  4.         path = "/" 
  5.     } 
  6.     let layer = { 
  7.         method: "middle"
  8.         path, 
  9.         handler 
  10.     } 
  11.     app.routes.push(layer) 

看,是不是很巧妙,很容易。

我們?cè)囍L問(wèn)路徑“/middle”

咦?第一個(gè)中間件沒(méi)有執(zhí)行,為什么呢?

對(duì)了,使用中間件的時(shí)候,最后要執(zhí)行next(),才能交給下一個(gè)中間件或者路由執(zhí)行。

當(dāng)我們請(qǐng)求“/middle”路徑的時(shí)候,可以看到確實(shí)請(qǐng)求成功,中間件也成功執(zhí)行。說(shuō)明我們的邏輯沒(méi)有問(wèn)題。

實(shí)際上,中間件已經(jīng)完成了,但是別忘了,還有個(gè)錯(cuò)誤中間件?

什么是錯(cuò)誤中間件?

錯(cuò)誤處理中間件函數(shù)的定義方式與其他中間件函數(shù)基本相同,差別在于錯(cuò)誤處理函數(shù)有四個(gè)自變量而不是三個(gè),專門具有特征符 (err, req, res, next):

  1. app.use(function(err, req, res, next) { 
  2.   console.error(err.stack); 
  3.   res.status(500).send('Something broke!'); 
  4. }); 

當(dāng)我們的在執(zhí)行next()方法的時(shí)候,如果拋出了錯(cuò)誤,是會(huì)直接尋找錯(cuò)誤中間件執(zhí)行的,而不會(huì)去執(zhí)行其他的中間件或者路由。

舉個(gè)例子:

如圖所示,當(dāng)?shù)谝粋€(gè)中間件往next傳遞參數(shù)的時(shí)候,表示執(zhí)行出現(xiàn)了錯(cuò)誤。然后就會(huì)跳過(guò)其他陸游和中間件和路由,直接執(zhí)行錯(cuò)誤中間件。當(dāng)然,執(zhí)行完錯(cuò)誤中間件,就會(huì)繼續(xù)執(zhí)行后面的中間件。

例如:

如圖所示,錯(cuò)誤中間件的后面那個(gè)是會(huì)執(zhí)行的。

那原理該怎么實(shí)現(xiàn)呢?

很簡(jiǎn)單,直接看代碼解釋,只需在next里多加一層判斷即可:

  1. function next(err) { 
  2.     // 已經(jīng)迭代完整個(gè)數(shù)組,還是沒(méi)有找到匹配的路徑 
  3.     if (index === app.routes.length) return res.end('Cannot find '
  4.     let { method, path, handler } = app.routes[index++] // 每次調(diào)用next就去下一個(gè)layer 
  5.     if( err ){ // 如果有錯(cuò)誤,應(yīng)該尋找中間件執(zhí)行。 
  6.         if(handler.length === 4) { //找到錯(cuò)誤中間件 
  7.             handler(err,req,res,next
  8.         }else { // 繼續(xù)徐州 
  9.             next(err)  
  10.         } 
  11.     }else { 
  12.         if (method === 'middle') { // 處理中間件 
  13.             if (path === '/' || path === pathname || pathname.starWidth(path + '/')) { 
  14.                 handler(req, res, next
  15.             } else { // 繼續(xù)遍歷 
  16.                 next(); 
  17.             } 
  18.         } else { // 處理路由 
  19.             if ((method === m || method === 'all') && (path === pathname || path === "*")) { 
  20.                 handler(req, res); 
  21.             } else { 
  22.                 next(); 
  23.             } 
  24.         } 
  25.     } 

看代碼可見(jiàn)在next里判斷err有沒(méi)有值,就可以判斷需不需要查找錯(cuò)誤中間件來(lái)執(zhí)行了。

如圖所示,請(qǐng)求/middle路徑,成功執(zhí)行。

到此,express框架的實(shí)現(xiàn)就大功告成了。

學(xué)習(xí)總結(jié)

通過(guò)這次express手寫原理的實(shí)現(xiàn),更加深入地了解了express的使用,發(fā)現(xiàn):

  • 中間件和路由都是push進(jìn)一個(gè)routes數(shù)組里的。
  • 當(dāng)執(zhí)行中間件的時(shí)候,會(huì)傳遞next,使得下一個(gè)中間件或者路由得以執(zhí)行。
  • 當(dāng)執(zhí)行到路由的時(shí)候就不會(huì)傳遞next,也使得routes的遍歷提前結(jié)束。
  • 當(dāng)執(zhí)行完錯(cuò)誤中間件后,后面的中間件或者路由還是會(huì)執(zhí)行的。

 

責(zé)任編輯:武曉燕 來(lái)源: 前端陽(yáng)光
相關(guān)推薦

2020-11-24 07:48:32

React

2020-10-20 09:12:57

axios核心原理

2022-08-27 13:49:36

ES7promiseresolve

2020-10-23 09:26:57

React-Redux

2021-05-08 07:53:33

面試線程池系統(tǒng)

2022-04-01 07:52:42

JavaScript防抖節(jié)流

2022-10-31 11:10:49

Javavolatile變量

2023-11-28 17:49:51

watch?computed?性能

2020-10-15 12:52:46

SpringbootJava編程語(yǔ)言

2021-04-22 07:49:51

Vue3Vue2.xVue3.x

2025-07-18 07:19:00

2024-08-22 10:39:50

@Async注解代理

2025-03-07 00:00:10

2024-03-05 10:33:39

AOPSpring編程

2020-12-09 10:29:53

SSH加密數(shù)據(jù)安全

2020-11-02 09:35:04

ReactHook

2020-12-03 08:14:45

Axios核心Promise

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫(kù)

2024-02-29 16:49:20

volatileJava并發(fā)編程

2024-11-19 15:13:02

點(diǎn)贊
收藏

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

韩国av一区二区| 91精品入口| 国产精品久久久久影院| 92裸体在线视频网站| 欧美黄色免费看| 国产精品香蕉| 欧美日韩一区视频| 日韩视频一二三| 日本在线丨区| 国产真实乱对白精彩久久| 国外视频精品毛片| 国产美女网站视频| 乱中年女人伦av一区二区| 在线观看一区二区视频| 2022中文字幕| 久草在现在线| 成人免费看黄yyy456| 国产女人18毛片水18精品| 国产精选第一页| 久久综合88| 日韩精品视频在线观看网址| 激情五月婷婷基地| gay欧美网站| 一区二区免费看| 亚洲人一区二区| 青青草视频在线观看| 国产成人一区在线| 成人高清视频观看www| 久久精品视频7| 黄色精品一区| 欧美精品制服第一页| 亚洲女同二女同志奶水| 亚洲激情播播| 亚洲国产黄色片| 日批视频免费看| 国产日韩欧美中文在线| 欧美在线观看你懂的| 女人和拘做爰正片视频| 超碰在线最新网址| 亚洲精品菠萝久久久久久久| 亚洲伊人婷婷| av网站在线免费观看| 久久午夜色播影院免费高清| 国产精品污www一区二区三区| 国产av一区二区三区| 另类中文字幕网| 日韩美女主播视频| 亚洲GV成人无码久久精品| 亚洲美女视频在线免费观看| 欧美激情一区二区久久久| 欧美大片xxxx| 你懂的视频一区二区| 精品国产欧美成人夜夜嗨| 人妻互换一区二区激情偷拍| 日韩欧美不卡| 日韩一区二区福利| 侵犯稚嫩小箩莉h文系列小说| 99久久久久| 日韩中文字幕国产精品| 91av手机在线| 偷偷www综合久久久久久久| 色婷婷av一区二区三区在线观看| 麻豆一区在线观看| 欧美国产一级| 久久69精品久久久久久久电影好| 欧美日韩精品一区二区三区视频播放| 最新欧美人z0oozo0| 久久99久久亚洲国产| 久久久无码精品亚洲国产| 精品动漫3d一区二区三区免费版| 午夜精品福利电影| 久久99国产综合精品免费| 另类图片国产| 国产欧美精品一区二区三区-老狼 国产欧美精品一区二区三区介绍 国产欧美精品一区二区 | 中文字幕 自拍| 成人精品影院| 欧美日本精品在线| 毛片基地在线观看| 日韩国产一区二| 成人高清视频观看www| 亚洲xxxx天美| 国产午夜亚洲精品理论片色戒| 亚洲精品在线免费看| 怡红院在线观看| 精品国产乱码久久久久久虫虫漫画| 成人黄色片视频| 亚洲人成网站在线在线观看| 精品黑人一区二区三区久久| 久久久久亚洲av无码专区桃色| 日韩欧美综合| 国内精品模特av私拍在线观看| 欧美性猛交xxxx乱大交hd| 韩日av一区二区| 精品国产乱码久久久久| 日韩三级影院| 午夜精品福利在线| 欧美成人福利在线观看| 成人av影音| 影音先锋欧美精品| 久久影院一区二区| 日日摸夜夜添夜夜添亚洲女人| 亚洲精品欧美日韩专区| 嫩草在线播放| 亚洲综合免费观看高清完整版 | 日韩精品久久一区二区三区| 黄网站在线播放| 欧美日韩精品在线观看| 久久婷婷中文字幕| 九色成人国产蝌蚪91| 久久夜色撩人精品| 亚洲黄网在线观看| 国产成人精品1024| 亚洲欧洲精品一区二区| 男人av在线播放| 日韩视频在线一区二区| 91导航在线观看| 亚洲精品美女91| 亚洲最大的免费| h视频在线免费| 欧美日韩免费区域视频在线观看| 一级日本黄色片| 日韩av大片| 日韩免费观看av| 午夜影院在线视频| 亚洲永久免费av| 午夜福利123| 91一区在线| 日韩美女免费视频| 香蕉视频911| 亚洲国产中文字幕在线视频综合| 午夜福利123| 91综合网人人| 国产美女精彩久久| 黄色大片在线看| 精品欧美激情精品一区| 天天看片天天操| 精品视频99| 国产成人久久精品| 国产福利小视频在线| 欧美性猛交视频| 538国产视频| 亚洲国产婷婷| 国产一区高清视频| 国产激情视频在线看| 亚洲国产一区二区三区四区| 免费无码毛片一区二区app| 国产一区二区三区黄视频| 一区二区在线高清视频| 另类一区二区三区| 久久久国产在线视频| 91国在线视频| 北京富婆泄欲对白| 色哟哟中文字幕| 亚洲精品第1页| 亚欧精品在线视频| 欧美极品一区二区三区| 亚洲一区久久久| 在线播放免费av| 日韩亚洲电影在线| 久久这里只有精品国产| 国产99久久久精品| 精品国产一区二区三区四区四 | 色综合久久网| 国产精品视频导航| av毛片在线看| 欧美mv和日韩mv国产网站| 国产无遮挡aaa片爽爽| www.久久精品| 国产免费人做人爱午夜视频| 欧美亚洲国产一区| 亚洲999一在线观看www| 好吊日av在线| 亚洲毛片在线免费观看| 国产精品sm调教免费专区| 中文字幕亚洲一区二区av在线| 又黄又爽又色的视频| 在线观看一区| 日本午夜精品一区二区三区| 日韩欧国产精品一区综合无码| 欧美美最猛性xxxxxx| 亚洲三区在线播放| 欧美日韩国产一级片| 免费一级肉体全黄毛片| 91视频免费观看| av污在线观看| 亚洲福利精品| 午夜久久资源| 大桥未久女教师av一区二区| 欧洲美女免费图片一区| 免费av不卡| 亚洲精品成a人在线观看| 中文字幕乱码视频| 亚洲妇熟xx妇色黄| 1024在线看片| caoporn国产一区二区| 午夜在线观看av| 亚洲黄色成人| 精品国产无码在线| 最新亚洲精品| y111111国产精品久久婷婷| xxxxxx欧美| 欧美国产精品人人做人人爱| 电影av一区| 亚洲福利在线视频| 国产精品美女一区| 一本久道中文字幕精品亚洲嫩| 欧美 日韩 国产 一区二区三区| wwww国产精品欧美| 三大队在线观看| 蜜臀av亚洲一区中文字幕| 日本在线xxx| 一区二区免费不卡在线| 日韩精品欧美在线| 日韩精品免费一区二区夜夜嗨| 亚洲一区久久久| 日日夜夜亚洲| 日韩av日韩在线观看| 超碰97免费在线| 欧美理论电影在线播放| a√在线中文网新版址在线| 亚洲国产精品字幕| 朝桐光av在线一区二区三区| 久久五月精品| 亚洲线精品一区二区三区| 少妇视频在线播放| 久久亚洲精精品中文字幕早川悠里| 国产毛片av在线| 狠狠色狠色综合曰曰| 激情五月婷婷在线| 国产精品剧情在线亚洲| 爱爱的免费视频| 成人av第一页| 美女流白浆视频| 韩国成人精品a∨在线观看| 丁香婷婷激情网| 午夜综合激情| 国产亚洲欧美在线视频| 精品白丝av| 被灌满精子的波多野结衣| 欧美一区二区三区久久精品茉莉花| 亚洲成色www久久网站| 国产91一区| 日本高清一区| 精品国产123区| 午夜午夜精品一区二区三区文| 深夜福利久久| 亚洲二区三区四区| 大胆日韩av| 艳色歌舞团一区二区三区| 欧美理论视频| 水蜜桃一区二区三区| 成人羞羞网站入口免费| 日本午夜精品一区二区| 欧美日韩国产一区二区三区不卡 | 午夜欧洲一区| 欧美人与性禽动交精品| 国产区精品区| 亚洲自拍偷拍二区| 午夜欧美视频| 免费国产黄色网址| 久久夜色精品| 亚洲一级片网站| 国产麻豆精品95视频| 精品国产aⅴ一区二区三区东京热 久久久久99人妻一区二区三区 | 日本一区二区在线看| 夜夜爽www精品| 午夜亚洲福利| 欧美 国产 综合| 日韩1区2区3区| 亚洲天堂av一区二区三区| 高清视频一区二区| 捆绑凌虐一区二区三区| 国产日本欧洲亚洲| 欧美性生交大片| 亚洲专区一二三| 波多野结衣大片| 欧美一级专区免费大片| 人人妻人人澡人人爽久久av | 欧美午夜一区二区三区免费大片| 在线观看毛片网站| 精品国产伦一区二区三区观看体验 | 91插插插插插插| 福利一区视频在线观看| 一区二区 亚洲| 亚洲成人xxx| 自拍视频在线网| 国内精品久久久久久| 日韩欧美少妇| 成人一区二区三区四区| 免费福利视频一区| 伊人久久大香线蕉午夜av| 日韩视频一区二区三区在线播放免费观看 | 精品无码人妻一区二区免费蜜桃| 亚洲精品国产成人久久av盗摄| 青青操免费在线视频| 欧美视频一二三区| av高清一区二区| 国产亚洲欧美视频| 成人三级小说| 成人黄色在线播放| 亚洲小说图片视频| 男女裸体影院高潮| 日韩av一级片| 国产黄色三级网站| 亚洲免费成人av| 波多野结衣爱爱| 亚洲国产日韩欧美在线动漫| 久久99精品久久| 日本久久亚洲电影| 一区二区在线免费播放| 亚洲国产一区二区三区在线播| 99pao成人国产永久免费视频| 中文字幕一区二区在线观看视频 | www.xx日本| 一本到不卡精品视频在线观看| www.黄色av| 日韩中文字幕在线看| 韩国成人漫画| 国产精品一区二区三区免费观看| 久久精品免费一区二区三区| 黄色一级二级三级| 91小视频免费观看| 国产一级二级毛片| 日韩午夜激情免费电影| 免费黄网站在线| 国产精品久久91| 久久91精品| 日本少妇高潮喷水视频| 国产成人精品一区二| 在线免费看av网站| 欧美日韩国产首页在线观看| 国家队第一季免费高清在线观看| 欧美亚洲一区在线| 麻豆一区二区麻豆免费观看| 国产成人永久免费视频| 国产激情视频一区二区三区欧美 | 亚洲va中文字幕| 亚洲va天堂va欧美ⅴa在线| 欧美成aaa人片在线观看蜜臀| 四虎国产精品免费久久5151| 神马影院午夜我不卡影院| 日韩电影在线免费看| 伊人网伊人影院| 色国产综合视频| 成年人在线看| 国产精品中文字幕久久久| 热久久天天拍国产| 国产又大又黄又猛| 国产精品福利一区| 一级成人免费视频| 久久精品国产欧美激情| 国产精品一区三区在线观看| 无码毛片aaa在线| 高清国产午夜精品久久久久久| 69av.com| 亚洲成人av中文字幕| 日本免费一区二区六区| 欧美极品一区二区| 男人的j进女人的j一区| 久久精品亚洲a| 精品精品国产高清a毛片牛牛| 韩国成人二区| 日韩偷拍一区二区| 麻豆高清免费国产一区| 东方av正在进入| 亚洲大胆人体在线| 免费电影日韩网站| 伊人色综合影院| 国产精品一区二区在线看| 国产无遮挡免费视频| 亚洲片在线观看| 日韩城人网站| 国产色一区二区三区| 久久免费视频色| 国产又粗又猛又爽又黄的视频一| 欧美国产精品va在线观看| 亚洲69av| 欧美xxxxxbbbbb| 亚瑟在线精品视频| 国产毛片av在线| 99久久久久国产精品免费| 亚洲伦伦在线| 免费中文字幕av| 在线观看免费亚洲| 国产午夜精品久久久久免费视| 成人h在线播放| 久久福利影视| 在线观看黄网址| 日韩激情视频在线播放| 日韩伦理一区二区| 黄色动漫网站入口| 亚洲欧洲精品一区二区三区不卡| 色窝窝无码一区二区三区| 国产精品丝袜久久久久久高清| 欧美jizzhd精品欧美巨大免费| 国产精品无码永久免费不卡| 国产小视频你懂的| 精品国产3级a| 福利一区视频| 美女扒开大腿让男人桶|