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

手把手帶你用 82 行代碼實現一個簡易版 Express 框架

開發 前端
connect 的 repo 描述是:“Connect is a middleware layer for Node.js”,也就是一個 Node.js 的中間件層。中間件層是一個非常有用的機制,它類似一個插件系統,讓我們可以通過插拔的方式組合不同功能來處理請求。

本文將帶大家實現輕量級 web 框架 connect[1] 的主要功能,只要 82 行代碼就能搞定。

我并沒有標題黨,因為 Express 在 v3 版本之前就是基于 connect 進行封裝的,不過在 v4 版本就將 connect 依賴移除了[2],代碼被搬到 Express 倉庫里,并做了一些細微調整。因此某種程度上,學習 connect 就是在學習 Express。

connect 的 repo 描述是:“Connect is a middleware layer for Node.js”,也就是一個 Node.js 的中間件層。中間件層是一個非常有用的機制,它類似一個插件系統,讓我們可以通過插拔的方式組合不同功能來處理請求。

基本使用

先來看看 connect 的使用。

const connect = require('connect')

const app = connect()

// respond to all requests
app.use(function(req, res){
  res.end('Hello from Connect!\n')
})

// create node.js http server and listen on port
http.createServer(app).listen(3000)

跟 Express 一樣。

另外,app 上還提供了 .listen() 方法,用于替代 http.createServer(app).listen(3000) 的冗長寫法。

app.listen(3000) // 等價于 http.createServer(app).listen(3000)

再看看中間件的使用。

app.use(function middleware1(req, res, next) {
  // middleware 1
  next()
});
app.use(function middleware2(req, res, next) {
  // middleware 2
  next()
});

我們通過 app.use() 方法收集并使用中間件。

中間件就是一個函數,包含 3 個參數:req、res 還有 next()。在一個中間件內調用 next(),就進入到下一個中間件的執行。

同時,我們還可以為中間件指定路由,這樣中間件只在特定路徑下起作用。

app.use('/foo', function fooMiddleware(req, res, next) {
  // req.url starts with "/foo"
  next()
})
app.use('/bar', function barMiddleware(req, res, next) {
  // req.url starts with "/bar"
  next()
})

本質上,純中間件的寫法就是在設置根路由('/'),所以會對所有請求有效。

app.use(function middleware1(req, res, next) {
  // middleware 1
  next()
})
// 等同于
app.use('/', function middleware1(req, res, next) {
  // middleware 1
  next()
})

不過還有一類特殊中間件——異常中間件,專門用于處理前面流程里的異常錯誤。

// regular middleware
app.use(function (req, res, next) {
  // i had an error
  next(new Error('boom!'));
});

// error middleware for errors that occurred in middleware
// declared before this
app.use(function onerror(err, req, res, next) {
  // an error occurred!
});

異常中間件必須是 4 個參數,第一個參數就是 error,對應前面流程中傳遞給 next() 的 Error 對象。

以上,我們就講完了 connect 庫的基本使用。接下來,就著手實現。

代碼實現

基于 connect v3.7.0 版本[3]。

剛學 Node.js 的時候,我們學到第一個例子,可能就是啟動一個會說“Hello World”的服務器了。

const http = require('node:http')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
  res.statusCode = 200
  res.setHeader('Content-Type', 'text/plain')
  res.end('Hello World\n')
})

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`)
})

回顧 connect 的使用。

const connect = require('connect')

const app = connect()

// respond to all requests
app.use(function(req, res){
  res.end('Hello from Connect!\n')
})

// create node.js http server and listen on port
app.listen(3000)

實現 app.listen()

我們已經知道 app.listen(3000) 內部實現就是 http.createServer(app).listen(3000)。

因此,我們先實現 .listen() 方法。

module.exports = function createApplication() {
  const app = {}

  app.listen = function listen(...args) {
    const server = require('node:http').createServer(/* ? */)
    return server.listen(...args);
  }

  return app
}

假設 app 是一個對象。不過,http.createServer(/* ? */) 中的 ? 內容該如何實現呢?

實現 app.use()

前一步,我們做了 app.use() 的調用。

// respond to all requests
app.use(function(req, res){
  res.end('Hello from Connect!\n')
})

所以,當服務啟動后,訪問 localhost:3000 時,應該返回 "Hello from Connect!" 的文本。

同時,app.use() 又支持重復調用。

// respond to all requests
app.use(function(req, res, next) {
  console.log('log req.url', req.url)
  next()
})

// respond to all requests
app.use(function(req, res) {
  res.end('Hello from Connect!\n')
})

那我們就考慮先用個數組,把通過 app.use() 調用傳入進來的回調函數存起來。

module.exports = function createApplication() {
  const app = {}
 app.stack = []
  
  app.use = function use(route, fn) {
   let path = route
   let handle = fn

        // default route to '/'
   if (typeof route !== 'string') {
      path = '/'
      handle = route
    }
    
    this.stack.push({ route: path, handle })
    return this
  }
  
  app.listen = function listen(...args) {
    const server = require('node:http').createServer(/* ? */)
    return server.listen(...args)
  }

  return app
}

我們把調用 app.use() 傳入的中間件都存到了 app.stack 里。

根據定義可知,http.createServer(/* ? */) 中的 ? 內容應該是一個函數。針對當前場景,它是用來處理 stack 中的這些中間件的。

實現 app.handle()

我們把這些邏輯寫在 app.handle() 內。

module.exports = function createApplication() {
  const app = {}
  app.stack = []

  // ...

  app.listen = function listen(...args) {
    const server = require('node:http').createServer(app.handle.bind(app))
    return server.listen(...args)
  }

  app.handle = function handle(res, res) {
    // TODO
  }

  return app
}

每當請求來臨,都由 app.handle 負責處理。

app.handle 的主要邏輯主要是處理 3 件事情。

  1. 獲取當前要處理的路由,沒有的話就交由最終處理函數 done
  2. 路由不匹配就跳過
  3. 路由匹配就執行當前中間件
app.handle = function handle(req, res) {
  let index = 0

  const done = function (err) { /* ... */ }

  function next(err) {
    // next callback
    const layer = app.stack[index++]

    // 1) all done
    if (!layer) {
      setImmdiate(done, err)
      return
    }

    // route data
    const path = require('node:url').parse(req.url).pathname
    const route = layer.route

    // 2) skip this layer if the route doesn't match
    if (!path.toLowerCase().startsWith(route.toLowerCase())) {
      return next(err)
    }

    // 3) call the layer handle
    const arity = handle.length
    const hasError = !!err
    let error = err

    try {
      if (hasError && arity === 4) {
        // error-handling middleware
        layer.handle(err, req, res, next)
        return
      } else if (!hasError && arity < 4) {
        // request-handling middleware
        layer.handle(req, res, next)
        return
      }
    } catch (e) {
      error = e
    }

    next(error)
  }

  next()
}

以上的關鍵處理就封裝在 next() 函數中。而 next() 函數就是傳遞給 connect 中間件的 next 參數。

這樣,每次請求進來,我們都會從 app.stack 的第一個中間件(stack[0])開始處理,就實現了以 next 參數為連接橋梁的中間件機制。

值得注意的是調用當前中間件的邏輯,當我們調用 layer.handle(err, req, res, next)/layer.handle(req, res, next) 時,處理流程會流入中間件內部,當內部調用 next() 函數后,控制權會重新回到 app.handle,繼續處理隊列中的下一個中間件。

當請求最終沒有任何中間件可以處理時,就會流入到 done,這是最終處理器。處理器內部,會根據是否存在錯誤,分別返回 404 或 5xx 響應。

const done = function (err) {
  if (err) {
    res.statusCode = err.status ?? err.statusCode ?? 500
    res.statusMessage = require('node:http').STATUS_CODES[404]
  } else {
    res.statusCode = 404
    res.statusMessage = `Cannot ${req.method} ${require('node:url').parse(req.url).pathname}`
  }
  res.end(`${res.statusCode} ${res.statusMessage}`)
}

至此,我們基本寫完了所有的邏輯。

當然,有一個地方,可以做一個小小的優化。將 http.createServer(app.handle.bind(app)) 簡化成 http.createServer(this),不過此時 app 就不能是對象,而是函數了。

module.exports = function createApplication() {
 function app(req, res) { app.handle(req, res) }

  // ...
  
  app.listen = function listen(...args) {
    const server = require('node:http').createServer(app)
    return server.listen(...args)
  }

  // ...
  
 return app
}

最后,我們整體來回顧一下。

module.exports = function createApplication() {
  function app(req, res) { app.handle(req, res) }
  app.stack = []

  app.use = function use(route, fn) {
    let path = route
    let handle = fn
    
    // default route to '/'
    if (typeof route !== 'string') {
      path = '/'
      handle = route
    }

    this.stack.push({ route: path, handle })
    return this
  }

  app.listen = function listen(...args) {
    const server = require('node:http').createServer(app)
    return server.listen(...args)
  }

  app.handle = function handle(req, res) {
    let index = 0

    const done = function (err) {
      if (err) {
        res.statusCode = err.status ?? err.statusCode ?? 500
        res.statusMessage = require('node:http').STATUS_CODES[404]
      } else {
        res.statusCode = 404
        res.statusMessage = `Cannot ${req.method} ${require('node:url').parse(req.url).pathname}`
      }
      res.end(`${res.statusCode} ${res.statusMessage}`)
    }

    function next(err) {
      // next callback
      const layer = app.stack[index++]

      // 1) all done
      if (!layer) {
        setImmediate(done, err)
        return
      }

      const path = require('node:url').parse(req.url).pathname
      const route = layer.route
      
      // 2) skip this layer if the route doesn't match
      if (!path.toLowerCase().startsWith(route.toLowerCase())) {
        return next(err)
      }

      // 3) call the layer handle
      const arity = handle.length
      const hasError = !!err
      let error = err

      try {
        // error-handling middleware
        if (hasError && arity === 4) {
          layer.handle(err, req, res, next)
          return
        // request-handling middleware
        } else if (!hasError && arity < 4) { 
          layer.handle(req, res, next)
          return
        }
      } catch (e) {
        error = e
      }

      next(error)
    }

    next()
  }
  
  return app
}

連上注釋,我們只用了 82 行代碼,就實現了 connect 的主要功能。

總結

本文帶大家實現了輕量級 Web 框架 connect 的主要功能,同樣這也是一個簡易版本  Express!

實現核心是 2 個函數。

  • app.use(route, fn):用于收集中間件
  • app.handle(res, req):用于消費中間件。主要邏輯位于 next() 函數,這是傳遞給中間件的 next 參數。每一次接收請求來臨時,都由 app.handle 負責處理

而這兩個函數之間的橋梁就是 app.stack。

行文最后,給大家留一個思考題。

connect() 實例的真實實現,是支持作為子應用,掛載到父應用之上的,也就是下面的用法。

const connect = require('connect')
const app = connect()
const blogApp = connect()

app.use('/blog', blogApp)
app.listen(3000)

甚至 http.Server 實例也支持掛載。

const connect = require('connect')
const app = connect()

const blog = http.createServer(function(req, res){
  res.end('blog')
})

app.use('/blog', blog)

那是如何實現呢?

大家可以參照 app.use()[4] 函數的源碼進行學習。

感謝的你的閱讀,再見~

參考資料

[1]connect: https://github.com/senchalabs/connect

[2]在 v4 版本就將 connect 依賴移除了: https://github.com/expressjs/express/compare/3.21.2...4.0.0#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519

[3]connect v3.7.0 版本: https://github.com/senchalabs/connect/blob/3.7.0/index.js

[4]app.use(): https://github.com/senchalabs/connect/blob/3.7.0/index.js#L76

責任編輯:武曉燕 來源: 寫代碼的寶哥
相關推薦

2022-11-07 18:36:03

組件RPC框架

2017-10-29 21:43:25

人臉識別

2022-10-20 11:49:49

JS動畫幀,CSS

2020-12-15 08:58:07

Vue編輯器vue-cli

2017-11-27 15:17:24

PythonMonkey腳本

2017-07-19 13:27:44

前端Javascript模板引擎

2022-02-28 12:07:56

RxJS函數式

2014-01-22 09:19:57

JavaScript引擎

2022-06-28 15:29:56

Python編程語言計時器

2024-07-16 11:26:35

微前端代碼JS

2017-10-27 10:29:35

人臉識別UbuntuPython

2017-09-20 16:39:31

云主機網站MySQL

2017-09-20 12:36:50

云主機網站MySQL

2022-09-22 12:38:46

antd form組件代碼

2023-03-29 10:02:36

2023-01-30 09:27:57

開發自動化配置

2020-05-09 09:59:52

Python數據土星

2021-06-22 10:43:03

Webpack loader plugin

2022-08-11 07:32:51

Starter自動裝配

2021-10-09 13:08:58

C++STLSet
點贊
收藏

51CTO技術棧公眾號

成人精品视频.| 成人爽a毛片免费啪啪红桃视频| 久久久久国产精品麻豆| 国产精品91在线| 精品国产视频在线观看| 国产成人精品亚洲线观看| 一本色道久久综合亚洲aⅴ蜜桃| 午夜欧美性电影| 亚洲AV无码一区二区三区性| 日韩精品久久久久久| 欧美成人免费网| 国产偷人妻精品一区| 国产精品国产一区二区三区四区| 亚洲mv大片欧洲mv大片| 精品国内二区三区| 中文字幕在线观看第三页| 成人影院在线看| 久久网站最新地址| 亚洲在线观看视频| 亚洲影院在线播放| 欧美激情麻豆| 色哟哟亚洲精品一区二区| 丝袜熟女一区二区三区| 天天综合在线观看| 日韩欧美精品网址| 精品久久久久久无码中文野结衣| lutube成人福利在线观看| 成人免费高清视频在线观看| 国产欧美一区二区| 国产精品免费av一区二区| 先锋资源久久| 亚洲一区二区久久| 五十路六十路七十路熟婆 | 自拍亚洲一区| 日韩亚洲电影在线| 欧美激情精品久久久久久小说| 日日夜夜天天综合入口| 日韩一区有码在线| 先锋影音亚洲资源| 国产系列在线观看| 久久夜色精品国产欧美乱极品| 91沈先生播放一区二区| 亚洲综合精品视频| 日日嗨av一区二区三区四区| 91福利视频网| 99精品视频99| 一区二区三区精品视频在线观看 | 黄色片在线观看网站| 久久国产亚洲| 在线中文字幕日韩| 亚洲最大成人综合网| 国产毛片一区二区三区 | 欧美尤物美女在线| 中文字幕av一区二区三区免费看 | 午夜剧场免费看| 香蕉成人app| 欧美不卡123| 自拍偷拍激情视频| 一本一道久久a久久| 日韩欧美在线网站| 曰本三级日本三级日本三级| 99香蕉久久| 精品成人一区二区三区| 亚洲视频天天射| 加勒比色老久久爱综合网| 精品99一区二区| 亚洲中文字幕一区| 日韩大胆成人| 亚洲一区二区久久久| 国产午夜福利一区| 天天综合久久| 欧美激情a在线| 国产一级生活片| 一区二区91| 国产精品成人一区二区三区吃奶| 又骚又黄的视频| 国内精品伊人久久久久影院对白| 亚洲www在线观看| 风流少妇一区二区三区91| 成人午夜精品一区二区三区| 精品亚洲一区二区三区四区五区高| 香蕉人妻av久久久久天天| 99久久久精品| 先锋在线资源一区二区三区| av男人的天堂在线| 综合久久久久久| 日韩中字在线观看| 日韩a**中文字幕| 91精品国产美女浴室洗澡无遮挡| 95视频在线观看| 国产探花一区| 欧美大荫蒂xxx| 欧美超碰在线观看| 国产精品一区二区三区网站| 精品午夜一区二区| 欧美激情视频在线播放| 午夜精品在线看| 婷婷六月天在线| 日韩一二三区| 国产亚洲精品综合一区91| 国产传媒免费在线观看| 国产视频一区三区| 成人性生交大片免费看视频直播 | 中文字幕亚洲无线码a| 欧美精品入口蜜桃| 日本一不卡视频| 国产精品免费看一区二区三区| 户外极限露出调教在线视频| 亚洲精品国久久99热| 成年人免费在线播放| 韩国一区二区三区视频| 亚洲人成电影网站| 精品肉丝脚一区二区三区| 日本中文字幕一区二区视频| 99热国产免费| 日本三级在线播放完整版| 五月天视频一区| 黄色片子免费看| 欧美日韩第一| 欧洲亚洲免费视频| 超碰97免费在线| 国产ts人妖一区二区| 日本不卡免费新一二三区| 午夜在线激情影院| 欧美日韩国产一区二区三区地区| www.com日本| 婷婷中文字幕一区| 国产精品免费久久久久影院| 天堂а√在线8种子蜜桃视频 | 欧美大片免费久久精品三p| 欧美黄色一级生活片| 国产日韩亚洲| 精品久久久久久一区| 在线视频国产区| 这里只有精品99re| 娇小11一12╳yⅹ╳毛片| 麻豆久久精品| 黄色一区三区| 蜜桃传媒在线观看免费进入| 欧美一区二区三区不卡| 欧美成人短视频| 日韩二区三区在线观看| 欧美日韩国产综合视频在线| 国模私拍一区二区国模曼安| 亚洲精品在线观| 久久久夜色精品| 国产高清亚洲一区| 久久久久久久久网| 精品午夜av| 欧美成人激情在线| 99久久久久成人国产免费| 中文字幕一区二区三区在线不卡| 免费在线观看的毛片| 精品国产一区二区三区av片| 国产成人久久久| www免费网站在线观看| 欧美伊人精品成人久久综合97| 欧美激情 一区| 日韩电影在线免费观看| 日韩一本精品| 久久伊人国产| 粗暴蹂躏中文一区二区三区| 国产后入清纯学生妹| 一区二区三区在线影院| 亚洲三级在线视频| 亚洲视频综合| 久久99热只有频精品91密拍| 成人黄色免费短视频| 中文字幕精品久久久久| 国产视频在线免费观看| 亚洲午夜免费视频| 国产精品探花一区二区在线观看| 亚洲欧美网站| 亚洲一区二区三区精品动漫| 日韩精品三级| 2019亚洲男人天堂| 国产福利在线| 91麻豆精品国产自产在线| 在线观看成人毛片| 91亚洲男人天堂| 欧美精品久久久久久久久25p| 中文字幕一区二区av| 国产一区免费| 日韩av电影资源网| 欧美老女人性视频| 无套内谢的新婚少妇国语播放| 色老综合老女人久久久| 狂野欧美性猛交| 国产·精品毛片| 精品99在线视频| 欧美99久久| 欧美日韩在线一二三| 深夜福利亚洲| 7777免费精品视频| 男人天堂手机在线| 亚洲精品国产拍免费91在线| 中文字幕有码视频| 亚洲成人免费观看| 99自拍偷拍视频| jizz一区二区| 性欧美在线视频| 国产精品日本欧美一区二区三区| 一区二区精品视频| 国产欧美自拍一区| 成人免费视频网址| 黑人巨大亚洲一区二区久| 久久99久久99精品中文字幕| 韩国精品视频| 亚洲精品99久久久久中文字幕| 亚洲一卡二卡在线| 欧美丝袜美女中出在线| 久草视频免费在线| 国产精品污www在线观看| 亚洲の无码国产の无码步美| 国产一区二区三区免费看| 狠狠操精品视频| 亚洲精品精选| www.在线观看av| 欧美肥老太太性生活| 欧美福利精品| 另类在线视频| 国产精品对白一区二区三区| 欧美国产中文高清| 国产欧美精品在线| 日本精品在线一区| 热re99久久精品国产66热| 97人人在线视频| 欧美国产视频日韩| av免费在线观看网址| 日韩亚洲综合在线| av一区在线观看| 国产一区二区三区在线观看视频| 头脑特工队2免费完整版在线观看| 欧美v日韩v国产v| 国产夫绿帽单男3p精品视频| 欧美日韩一本到| 在线视频1卡二卡三卡| 欧美中文一区二区三区| 中文字幕精品视频在线观看| 色网站国产精品| 日韩美一区二区| 色综合夜色一区| 亚洲欧美一区二区三区在线观看 | 久久久999国产| 色欧美激情视频在线| 最近2019中文免费高清视频观看www99 | 欧美亚洲精品天堂| 天天综合色天天综合色h| 18精品爽视频在线观看| 亚洲一区二区三区影院| 懂色av.com| 欧美日韩一区二区免费在线观看| 国产精品视频免费播放| 日韩欧美999| 亚洲毛片一区二区三区| 欧美最猛性xxxxx直播| 中文字幕av网站| 91精品婷婷国产综合久久竹菊| 国产欧美一区二区三区视频在线观看| 91麻豆精品国产91久久久资源速度| 99久久国产热无码精品免费| 精品国产乱码久久久久久蜜臀 | 欧美a级大片在线| 不卡视频一区二区| 牲欧美videos精品| 日韩理论片在线观看| 欧美wwwww| 日韩国产小视频| 国产视频一区在线观看一区免费| 欧美日韩亚洲一二三| 狠狠色丁香婷综合久久| 成熟妇人a片免费看网站| 久久新电视剧免费观看| 肉色超薄丝袜脚交69xx图片| 亚洲狠狠爱一区二区三区| 中文字幕免费在线观看视频| 欧美性受极品xxxx喷水| 国产av无码专区亚洲av| 亚洲精品720p| 亚洲搞黄视频| 久久久久久一区二区三区| 日韩天堂在线| 444亚洲人体| 网红女主播少妇精品视频| 亚洲欧美精品| 亚洲精品婷婷| 国内外成人免费在线视频| 成人三级伦理片| 国产精品久久久久久成人| 一区二区在线免费| 亚洲黄色免费观看| 欧美一区二区美女| 精品视频一二区| 九九九久久国产免费| 欧美极品影院| 国产欧美在线一区二区| 色综合蜜月久久综合网| 欧美性大战久久久久xxx| 狠狠色丁香九九婷婷综合五月| 国产麻豆xxxvideo实拍| 亚洲图片激情小说| 东京热一区二区三区四区| 欧美一级黄色片| 国产一级网站视频在线| 欧美极品少妇xxxxⅹ喷水 | 99re在线观看视频| 欧美日韩在线网站| 国产极品尤物在线| 国产一区二区导航在线播放| 30一40一50老女人毛片| 悠悠色在线精品| 这里只有精品9| 亚洲视频一区二区三区| 超碰在线视屏| 亚洲一区国产精品| 欧美激情另类| 国产又大又黄又粗又爽| 久久蜜桃一区二区| 日本在线视频中文字幕| 精品女同一区二区| 1stkiss在线漫画| 国产美女91呻吟求| av亚洲免费| 免费看a级黄色片| 久久综合九色综合97婷婷| 日韩免费在线视频观看| 欧美大胆人体bbbb| 国产剧情在线| 成人激情av在线| 日韩精品91| 日本激情视频在线播放| 久久久久一区二区三区四区| 国产精品美女久久久久av爽| 欧美成人午夜电影| 深夜国产在线播放| 91黄在线观看| 欧美日韩国产一区精品一区| 99视频在线观看视频| 亚洲欧美国产毛片在线| 99热这里只有精品3| 俺去了亚洲欧美日韩| 欧美高清免费| 制服诱惑一区| 国内精品自线一区二区三区视频| 少妇高潮惨叫久久久久| 欧美男男青年gay1069videost| 成黄免费在线| 国产在线不卡精品| 日韩精品首页| 中文字幕色网站| 一区二区三区四区高清精品免费观看 | 日韩午夜激情视频| 四虎影视成人| 国产在线视频欧美一区二区三区| 亚洲精品色图| 五级黄高潮片90分钟视频| 日本精品一区二区三区高清| 成人在线视频成人| 国产主播欧美精品| 午夜国产精品视频| 喷水视频在线观看| 在线影院国内精品| 日本中文字幕伦在线观看| 91在线观看免费| 激情久久五月| 国产jjizz一区二区三区视频| 欧美日韩一区小说| 婷婷在线播放| 免费一区二区三区| 美日韩一级片在线观看| 免费在线观看日韩| 精品无人区太爽高潮在线播放| 日韩美女在线看免费观看| 中文字幕一区二区三区四区五区人 | 热久久天天拍国产| 免费人成视频在线播放| 黑人巨大精品欧美一区二区免费| porn亚洲| 风间由美久久久| 天堂精品中文字幕在线| 国产成人av免费在线观看| 亚洲国产一区二区三区四区 | 亚洲tv在线观看| 亚洲精选一区| 日日操免费视频| 亚洲国产精品久久久久| avav成人| 日本人体一区二区| 国产人久久人人人人爽| 国产xxxx孕妇| 国产精品久久久久久久一区探花 | 国产xxxxx在线观看| 成人欧美一区二区三区| 香港三日本三级少妇66| 91久久精品国产| 亚洲欧美日韩国产一区二区| 欧美一区免费观看| 日韩精品在线私人| 日韩精品视频中文字幕| 浓精h攵女乱爱av|