国产无遮挡裸体免费直播视频,久久精品国产蜜臀av,动漫在线视频一区二区,欧亚日韩一区二区三区,久艹在线 免费视频,国产精品美女网站免费,正在播放 97超级视频在线观看,斗破苍穹年番在线观看免费,51最新乱码中文字幕

node.js入門教程迷你書、node.js入門web應(yīng)用開發(fā)完全示例

 更新時(shí)間:2014年04月06日 22:53:11   作者:  
本書致力于教會(huì)你如何用Node.js來開發(fā)應(yīng)用,過程中會(huì)傳授你所有所需的“高級(jí)”JavaScript知識(shí)。本書絕不是一本“Hello World”的教程。

本書狀態(tài)

你正在閱讀的已經(jīng)是本書的最終版。因此,只有當(dāng)進(jìn)行錯(cuò)誤更正以及針對(duì)新版本Node.js的改動(dòng)進(jìn)行對(duì)應(yīng)的修正時(shí),才會(huì)進(jìn)行更新。

本書中的代碼案例都在Node.js 0.6.11版本中測(cè)試過,可以正確工作。

讀者對(duì)象

本書最適合與我有相似技術(shù)背景的讀者: 至少對(duì)一門諸如Ruby、Python、PHP或者Java這樣面向?qū)ο蟮恼Z(yǔ)言有一定的經(jīng)驗(yàn);對(duì)JavaScript處于初學(xué)階段,并且完全是一個(gè)Node.js的新手。

這里指的適合對(duì)其他編程語(yǔ)言有一定經(jīng)驗(yàn)的開發(fā)者,意思是說,本書不會(huì)對(duì)諸如數(shù)據(jù)類型、變量、控制結(jié)構(gòu)等等之類非常基礎(chǔ)的概念作介紹。要讀懂本書,這些基礎(chǔ)的概念我都默認(rèn)你已經(jīng)會(huì)了。

然而,本書還是會(huì)對(duì)JavaScript中的函數(shù)和對(duì)象作詳細(xì)介紹,因?yàn)樗鼈兣c其他同類編程語(yǔ)言中的函數(shù)和對(duì)象有很大的不同。

本書結(jié)構(gòu)

讀完本書之后,你將完成一個(gè)完整的web應(yīng)用,該應(yīng)用允許用戶瀏覽頁(yè)面以及上傳文件。

當(dāng)然了,應(yīng)用本身并沒有什么了不起的,相比為了實(shí)現(xiàn)該功能書寫的代碼本身,我們更關(guān)注的是如何創(chuàng)建一個(gè)框架來對(duì)我們應(yīng)用的不同模塊進(jìn)行干凈地剝離。 是不是很玄乎?稍后你就明白了。

本書先從介紹在Node.js環(huán)境中進(jìn)行JavaScript開發(fā)和在瀏覽器環(huán)境中進(jìn)行JavaScript開發(fā)的差異開始。

緊接著,會(huì)帶領(lǐng)大家完成一個(gè)最傳統(tǒng)的“Hello World”應(yīng)用,這也是最基礎(chǔ)的Node.js應(yīng)用。

最后,會(huì)和大家討論如何設(shè)計(jì)一個(gè)“真正”完整的應(yīng)用,剖析要完成該應(yīng)用需要實(shí)現(xiàn)的不同模塊,并一步一步介紹如何來實(shí)現(xiàn)這些模塊。

可以確保的是,在這過程中,大家會(huì)學(xué)到JavaScript中一些高級(jí)的概念、如何使用它們以及為什么使用這些概念就可以實(shí)現(xiàn)而其他編程語(yǔ)言中同類的概念就無(wú)法實(shí)現(xiàn)。

該應(yīng)用所有的源代碼都可以通過 本書Github代碼倉(cāng)庫(kù):https://github.com/ManuelKiessling/NodeBeginnerBook/tree/master/code/application.

JavaScript與Node.js

JavaScript與你

拋開技術(shù),我們先來聊聊你以及你和JavaScript的關(guān)系。本章的主要目的是想讓你看看,對(duì)你而言是否有必要繼續(xù)閱讀后續(xù)章節(jié)的內(nèi)容。

如果你和我一樣,那么你很早就開始利用HTML進(jìn)行“開發(fā)”,正因如此,你接觸到了這個(gè)叫JavaScript有趣的東西,而對(duì)于JavaScript,你只會(huì)基本的操作——為web頁(yè)面添加交互。

而你真正想要的是“干貨”,你想要知道如何構(gòu)建復(fù)雜的web站點(diǎn) —— 于是,你學(xué)習(xí)了一種諸如PHP、Ruby、Java這樣的編程語(yǔ)言,并開始書寫“后端”代碼。

與此同時(shí),你還始終關(guān)注著JavaScript,隨著通過一些對(duì)jQuery,Prototype之類技術(shù)的介紹,你慢慢了解到了很多JavaScript中的進(jìn)階技能,同時(shí)也感受到了JavaScript絕非僅僅是window.open() 那么簡(jiǎn)單。 .

不過,這些畢竟都是前端技術(shù),盡管當(dāng)想要增強(qiáng)頁(yè)面的時(shí)候,使用jQuery總讓你覺得很爽,但到最后,你頂多是個(gè)JavaScript用戶,而非JavaScript開發(fā)者。

然后,出現(xiàn)了Node.js,服務(wù)端的JavaScript,這有多酷?。?/P>

于是,你覺得是時(shí)候該重新拾起既熟悉又陌生的JavaScript了。但是別急,寫Node.js應(yīng)用是一件事情;理解為什么它們要以它們書寫的這種方式來書寫則意味著——你要懂JavaScript。這次是玩真的了。

問題來了: 由于JavaScript真正意義上以兩種,甚至可以說是三種形態(tài)存在(從中世紀(jì)90年代的作為對(duì)DHTML進(jìn)行增強(qiáng)的小玩具,到像jQuery那樣嚴(yán)格意義上的前端技術(shù),一直到現(xiàn)在的服務(wù)端技術(shù)),因此,很難找到一個(gè)“正確”的方式來學(xué)習(xí)JavaScript,使得讓你書寫Node.js應(yīng)用的時(shí)候感覺自己是在真正開發(fā)它而不僅僅是使用它。

因?yàn)檫@就是關(guān)鍵: 你本身已經(jīng)是個(gè)有經(jīng)驗(yàn)的開發(fā)者,你不想通過到處尋找各種解決方案(其中可能還有不正確的)來學(xué)習(xí)新的技術(shù),你要確保自己是通過正確的方式來學(xué)習(xí)這項(xiàng)技術(shù)。

當(dāng)然了,外面不乏很優(yōu)秀的學(xué)習(xí)JavaScript的文章。但是,有的時(shí)候光靠那些文章是遠(yuǎn)遠(yuǎn)不夠的。你需要的是指導(dǎo)。

本書的目標(biāo)就是給你提供指導(dǎo)。

簡(jiǎn)短申明

業(yè)界有非常優(yōu)秀的JavaScript程序員。而我并非其中一員。

我就是上一節(jié)中描述的那個(gè)我。我熟悉如何開發(fā)后端web應(yīng)用,但是對(duì)“真正”的JavaScript以及Node.js,我都只是新手。我也只是最近學(xué)習(xí)了一些JavaScript的高級(jí)概念,并沒有實(shí)踐經(jīng)驗(yàn)。

因此,本書并不是一本“從入門到精通”的書,更像是一本“從初級(jí)入門到高級(jí)入門”的書。

如果成功的話,那么本書就是我當(dāng)初開始學(xué)習(xí)Node.js最希望擁有的教程。

服務(wù)端JavaScript

JavaScript最早是運(yùn)行在瀏覽器中,然而瀏覽器只是提供了一個(gè)上下文,它定義了使用JavaScript可以做什么,但并沒有“說”太多關(guān)于JavaScript語(yǔ)言本身可以做什么。事實(shí)上,JavaScript是一門“完整”的語(yǔ)言: 它可以使用在不同的上下文中,其能力與其他同類語(yǔ)言相比有過之而無(wú)不及。

Node.js事實(shí)上就是另外一種上下文,它允許在后端(脫離瀏覽器環(huán)境)運(yùn)行JavaScript代碼。

要實(shí)現(xiàn)在后臺(tái)運(yùn)行JavaScript代碼,代碼需要先被解釋然后正確的執(zhí)行。Node.js的原理正是如此,它使用了Google的V8虛擬機(jī)(Google的Chrome瀏覽器使用的JavaScript執(zhí)行環(huán)境),來解釋和執(zhí)行JavaScript代碼。

除此之外,伴隨著Node.js的還有許多有用的模塊,它們可以簡(jiǎn)化很多重復(fù)的勞作,比如向終端輸出字符串。

因此,Node.js事實(shí)上既是一個(gè)運(yùn)行時(shí)環(huán)境,同時(shí)又是一個(gè)庫(kù)。

要使用Node.js,首先需要進(jìn)行安裝。關(guān)于如何安裝Node.js,這里就不贅述了,可以直接參考官方的安裝指南。安裝完成后,繼續(xù)回來閱讀本書下面的內(nèi)容。

“Hello World”

好了,“廢話”不多說了,馬上開始我們第一個(gè)Node.js應(yīng)用:“Hello World”。

打開你最喜歡的編輯器,創(chuàng)建一個(gè)helloworld.js文件。我們要做就是向STDOUT輸出“Hello World”,如下是實(shí)現(xiàn)該功能的代碼:

復(fù)制代碼 代碼如下:
console.log("Hello World");

保存該文件,并通過Node.js來執(zhí)行:

復(fù)制代碼 代碼如下:
node helloworld.js

正常的話,就會(huì)在終端輸出Hello World 。

好吧,我承認(rèn)這個(gè)應(yīng)用是有點(diǎn)無(wú)趣,那么下面我們就來點(diǎn)“干貨”。

一個(gè)完整的基于Node.js的web應(yīng)用

用例

我們來把目標(biāo)設(shè)定得簡(jiǎn)單點(diǎn),不過也要夠?qū)嶋H才行:

1.用戶可以通過瀏覽器使用我們的應(yīng)用。
2.當(dāng)用戶請(qǐng)求http://domain/start時(shí),可以看到一個(gè)歡迎頁(yè)面,頁(yè)面上有一個(gè)文件上傳的表單。
3.用戶可以選擇一個(gè)圖片并提交表單,隨后文件將被上傳到http://domain/upload,該頁(yè)面完成上傳后會(huì)把圖片顯示在頁(yè)面上。
差不多了,你現(xiàn)在也可以去Google一下,找點(diǎn)東西亂搞一下來完成功能。但是我們現(xiàn)在先不做這個(gè)。

更進(jìn)一步地說,在完成這一目標(biāo)的過程中,我們不僅僅需要基礎(chǔ)的代碼而不管代碼是否優(yōu)雅。我們還要對(duì)此進(jìn)行抽象,來尋找一種適合構(gòu)建更為復(fù)雜的Node.js應(yīng)用的方式。

應(yīng)用不同模塊分析

我們來分解一下這個(gè)應(yīng)用,為了實(shí)現(xiàn)上文的用例,我們需要實(shí)現(xiàn)哪些部分呢?

1.我們需要提供Web頁(yè)面,因此需要一個(gè)HTTP服務(wù)器
2.對(duì)于不同的請(qǐng)求,根據(jù)請(qǐng)求的URL,我們的服務(wù)器需要給予不同的響應(yīng),因此我們需要一個(gè)路由,用于把請(qǐng)求對(duì)應(yīng)到請(qǐng)求處理程序(request handler)
3.當(dāng)請(qǐng)求被服務(wù)器接收并通過路由傳遞之后,需要可以對(duì)其進(jìn)行處理,因此我們需要最終的請(qǐng)求處理程序
4.路由還應(yīng)該能處理POST數(shù)據(jù),并且把數(shù)據(jù)封裝成更友好的格式傳遞給請(qǐng)求處理入程序,因此需要請(qǐng)求數(shù)據(jù)處理功能
5.我們不僅僅要處理URL對(duì)應(yīng)的請(qǐng)求,還要把內(nèi)容顯示出來,這意味著我們需要一些視圖邏輯供請(qǐng)求處理程序使用,以便將內(nèi)容發(fā)送給用戶的瀏覽器
6.最后,用戶需要上傳圖片,所以我們需要上傳處理功能來處理這方面的細(xì)節(jié)
我們先來想想,使用PHP的話我們會(huì)怎么構(gòu)建這個(gè)結(jié)構(gòu)。一般來說我們會(huì)用一個(gè)Apache HTTP服務(wù)器并配上mod_php5模塊。
從這個(gè)角度看,整個(gè)“接收HTTP請(qǐng)求并提供Web頁(yè)面”的需求根本不需要PHP來處理。

不過對(duì)Node.js來說,概念完全不一樣了。使用Node.js時(shí),我們不僅僅在實(shí)現(xiàn)一個(gè)應(yīng)用,同時(shí)還實(shí)現(xiàn)了整個(gè)HTTP服務(wù)器。事實(shí)上,我們的Web應(yīng)用以及對(duì)應(yīng)的Web服務(wù)器基本上是一樣的。

聽起來好像有一大堆活要做,但隨后我們會(huì)逐漸意識(shí)到,對(duì)Node.js來說這并不是什么麻煩的事。

現(xiàn)在我們就來開始實(shí)現(xiàn)之路,先從第一個(gè)部分--HTTP服務(wù)器著手。

構(gòu)建應(yīng)用的模塊

一個(gè)基礎(chǔ)的HTTP服務(wù)器

當(dāng)我準(zhǔn)備開始寫我的第一個(gè)“真正的”Node.js應(yīng)用的時(shí)候,我不但不知道怎么寫Node.js代碼,也不知道怎么組織這些代碼。
我應(yīng)該把所有東西都放進(jìn)一個(gè)文件里嗎?網(wǎng)上有很多教程都會(huì)教你把所有的邏輯都放進(jìn)一個(gè)用Node.js寫的基礎(chǔ)HTTP服務(wù)器里。但是如果我想加入更多的內(nèi)容,同時(shí)還想保持代碼的可讀性呢?

實(shí)際上,只要把不同功能的代碼放入不同的模塊中,保持代碼分離還是相當(dāng)簡(jiǎn)單的。

這種方法允許你擁有一個(gè)干凈的主文件(main file),你可以用Node.js執(zhí)行它;同時(shí)你可以擁有干凈的模塊,它們可以被主文件和其他的模塊調(diào)用。

那么,現(xiàn)在我們來創(chuàng)建一個(gè)用于啟動(dòng)我們的應(yīng)用的主文件,和一個(gè)保存著我們的HTTP服務(wù)器代碼的模塊。

在我的印象里,把主文件叫做index.js或多或少是個(gè)標(biāo)準(zhǔn)格式。把服務(wù)器模塊放進(jìn)叫server.js的文件里則很好理解。

讓我們先從服務(wù)器模塊開始。在你的項(xiàng)目的根目錄下創(chuàng)建一個(gè)叫server.js的文件,并寫入以下代碼:

復(fù)制代碼 代碼如下:

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);


搞定!你剛剛完成了一個(gè)可以工作的HTTP服務(wù)器。為了證明這一點(diǎn),我們來運(yùn)行并且測(cè)試這段代碼。首先,用Node.js執(zhí)行你的腳本:

node server.js
接下來,打開瀏覽器訪問http://localhost:8888/,你會(huì)看到一個(gè)寫著“Hello World”的網(wǎng)頁(yè)。

這很有趣,不是嗎?讓我們先來談?wù)凥TTP服務(wù)器的問題,把如何組織項(xiàng)目的事情先放一邊吧,你覺得如何?我保證之后我們會(huì)解決那個(gè)問題的。

分析HTTP服務(wù)器

那么接下來,讓我們分析一下這個(gè)HTTP服務(wù)器的構(gòu)成。

第一行請(qǐng)求(require)Node.js自帶的 http 模塊,并且把它賦值給 http 變量。

接下來我們調(diào)用http模塊提供的函數(shù): createServer 。這個(gè)函數(shù)會(huì)返回一個(gè)對(duì)象,這個(gè)對(duì)象有一個(gè)叫做 listen 的方法,這個(gè)方法有一個(gè)數(shù)值參數(shù),指定這個(gè)HTTP服務(wù)器監(jiān)聽的端口號(hào)。

咱們暫時(shí)先不管 http.createServer 的括號(hào)里的那個(gè)函數(shù)定義。

我們本來可以用這樣的代碼來啟動(dòng)服務(wù)器并偵聽8888端口:

復(fù)制代碼 代碼如下:

var http = require("http");

var server = http.createServer();
server.listen(8888);


這段代碼只會(huì)啟動(dòng)一個(gè)偵聽8888端口的服務(wù)器,它不做任何別的事情,甚至連請(qǐng)求都不會(huì)應(yīng)答。

最有趣(而且,如果你之前習(xí)慣使用一個(gè)更加保守的語(yǔ)言,比如PHP,它還很奇怪)的部分是 createSever() 的第一個(gè)參數(shù),一個(gè)函數(shù)定義。

實(shí)際上,這個(gè)函數(shù)定義是 createServer() 的第一個(gè)也是唯一一個(gè)參數(shù)。因?yàn)樵贘avaScript中,函數(shù)和其他變量一樣都是可以被傳遞的。

進(jìn)行函數(shù)傳遞

舉例來說,你可以這樣做:

復(fù)制代碼 代碼如下:

function say(word) {
  console.log(word);
}

function execute(someFunction, value) {
  someFunction(value);
}

execute(say, "Hello");
請(qǐng)仔細(xì)閱讀這段代碼!在這里,我們把 say 函數(shù)作為execute函數(shù)的第一個(gè)變量進(jìn)行了傳遞。這里返回的不是 say 的返回值,而是 say 本身!

這樣一來, say 就變成了execute 中的本地變量 someFunction ,execute可以通過調(diào)用 someFunction() (帶括號(hào)的形式)來使用 say 函數(shù)。

當(dāng)然,因?yàn)?say 有一個(gè)變量, execute 在調(diào)用 someFunction 時(shí)可以傳遞這樣一個(gè)變量。

我們可以,就像剛才那樣,用它的名字把一個(gè)函數(shù)作為變量傳遞。但是我們不一定要繞這個(gè)“先定義,再傳遞”的圈子,我們可以直接在另一個(gè)函數(shù)的括號(hào)中定義和傳遞這個(gè)函數(shù):

復(fù)制代碼 代碼如下:

function execute(someFunction, value) {
  someFunction(value);
}

execute(function(word){ console.log(word) }, "Hello");
我們?cè)?execute 接受第一個(gè)參數(shù)的地方直接定義了我們準(zhǔn)備傳遞給 execute 的函數(shù)。

用這種方式,我們甚至不用給這個(gè)函數(shù)起名字,這也是為什么它被叫做 匿名函數(shù) 。

這是我們和我所認(rèn)為的“進(jìn)階”JavaScript的第一次親密接觸,不過我們還是得循序漸進(jìn)。現(xiàn)在,我們先接受這一點(diǎn):在JavaScript中,一個(gè)函數(shù)可以作為另一個(gè)函數(shù)接收一個(gè)參數(shù)。我們可以先定義一個(gè)函數(shù),然后傳遞,也可以在傳遞參數(shù)的地方直接定義函數(shù)。

函數(shù)傳遞是如何讓HTTP服務(wù)器工作的

帶著這些知識(shí),我們?cè)賮砜纯次覀兒?jiǎn)約而不簡(jiǎn)單的HTTP服務(wù)器:

復(fù)制代碼 代碼如下:

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);


現(xiàn)在它看上去應(yīng)該清晰了很多:我們向 createServer 函數(shù)傳遞了一個(gè)匿名函數(shù)。

用這樣的代碼也可以達(dá)到同樣的目的:

復(fù)制代碼 代碼如下:

var http = require("http");

function onRequest(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);


也許現(xiàn)在我們?cè)搯栠@個(gè)問題了:我們?yōu)槭裁匆眠@種方式呢?

基于事件驅(qū)動(dòng)的回調(diào)

這個(gè)問題可不好回答(至少對(duì)我來說),不過這是Node.js原生的工作方式。它是事件驅(qū)動(dòng)的,這也是它為什么這么快的原因。

你也許會(huì)想花點(diǎn)時(shí)間讀一下Felix Geisendörfer的大作Understanding node.js,它介紹了一些背景知識(shí)。

這一切都?xì)w結(jié)于“Node.js是事件驅(qū)動(dòng)的”這一事實(shí)。好吧,其實(shí)我也不是特別確切的了解這句話的意思。不過我會(huì)試著解釋,為什么它對(duì)我們用Node.js寫網(wǎng)絡(luò)應(yīng)用(Web based application)是有意義的。

當(dāng)我們使用 http.createServer 方法的時(shí)候,我們當(dāng)然不只是想要一個(gè)偵聽某個(gè)端口的服務(wù)器,我們還想要它在服務(wù)器收到一個(gè)HTTP請(qǐng)求的時(shí)候做點(diǎn)什么。

問題是,這是異步的:請(qǐng)求任何時(shí)候都可能到達(dá),但是我們的服務(wù)器卻跑在一個(gè)單進(jìn)程中。

寫PHP應(yīng)用的時(shí)候,我們一點(diǎn)也不為此擔(dān)心:任何時(shí)候當(dāng)有請(qǐng)求進(jìn)入的時(shí)候,網(wǎng)頁(yè)服務(wù)器(通常是Apache)就為這一請(qǐng)求新建一個(gè)進(jìn)程,并且開始從頭到尾執(zhí)行相應(yīng)的PHP腳本。

那么在我們的Node.js程序中,當(dāng)一個(gè)新的請(qǐng)求到達(dá)8888端口的時(shí)候,我們?cè)趺纯刂屏鞒棠兀?/P>

嗯,這就是Node.js/JavaScript的事件驅(qū)動(dòng)設(shè)計(jì)能夠真正幫上忙的地方了——雖然我們還得學(xué)一些新概念才能掌握它。讓我們來看看這些概念是怎么應(yīng)用在我們的服務(wù)器代碼里的。

我們創(chuàng)建了服務(wù)器,并且向創(chuàng)建它的方法傳遞了一個(gè)函數(shù)。無(wú)論何時(shí)我們的服務(wù)器收到一個(gè)請(qǐng)求,這個(gè)函數(shù)就會(huì)被調(diào)用。

我們不知道這件事情什么時(shí)候會(huì)發(fā)生,但是我們現(xiàn)在有了一個(gè)處理請(qǐng)求的地方:它就是我們傳遞過去的那個(gè)函數(shù)。至于它是被預(yù)先定義的函數(shù)還是匿名函數(shù),就無(wú)關(guān)緊要了。

這個(gè)就是傳說中的 回調(diào) 。我們給某個(gè)方法傳遞了一個(gè)函數(shù),這個(gè)方法在有相應(yīng)事件發(fā)生時(shí)調(diào)用這個(gè)函數(shù)來進(jìn)行 回調(diào) 。

至少對(duì)我來說,需要一些功夫才能弄懂它。你如果還是不太確定的話就再去讀讀Felix的博客文章。

讓我們?cè)賮碜聊プ聊ミ@個(gè)新概念。我們?cè)趺醋C明,在創(chuàng)建完服務(wù)器之后,即使沒有HTTP請(qǐng)求進(jìn)來、我們的回調(diào)函數(shù)也沒有被調(diào)用的情況下,我們的代碼還繼續(xù)有效呢?我們?cè)囋囘@個(gè):

復(fù)制代碼 代碼如下:

var http = require("http");

function onRequest(request, response) {
  console.log("Request received.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

console.log("Server has started.");


注意:在 onRequest (我們的回調(diào)函數(shù))觸發(fā)的地方,我用 console.log 輸出了一段文本。在HTTP服務(wù)器開始工作之后,也輸出一段文本。

當(dāng)我們與往常一樣,運(yùn)行它node server.js時(shí),它會(huì)馬上在命令行上輸出“Server has started.”。當(dāng)我們向服務(wù)器發(fā)出請(qǐng)求(在瀏覽器訪問http://localhost:8888/ ),“Request received.”這條消息就會(huì)在命令行中出現(xiàn)。

這就是事件驅(qū)動(dòng)的異步服務(wù)器端JavaScript和它的回調(diào)啦!

(請(qǐng)注意,當(dāng)我們?cè)诜?wù)器訪問網(wǎng)頁(yè)時(shí),我們的服務(wù)器可能會(huì)輸出兩次“Request received.”。那是因?yàn)榇蟛糠址?wù)器都會(huì)在你訪問 http://localhost:8888 /時(shí)嘗試讀取 http://localhost:8888/favicon.ico )

服務(wù)器是如何處理請(qǐng)求的

好的,接下來我們簡(jiǎn)單分析一下我們服務(wù)器代碼中剩下的部分,也就是我們的回調(diào)函數(shù) onRequest() 的主體部分。

當(dāng)回調(diào)啟動(dòng),我們的 onRequest() 函數(shù)被觸發(fā)的時(shí)候,有兩個(gè)參數(shù)被傳入: request 和 response 。

它們是對(duì)象,你可以使用它們的方法來處理HTTP請(qǐng)求的細(xì)節(jié),并且響應(yīng)請(qǐng)求(比如向發(fā)出請(qǐng)求的瀏覽器發(fā)回一些東西)。

所以我們的代碼就是:當(dāng)收到請(qǐng)求時(shí),使用 response.writeHead() 函數(shù)發(fā)送一個(gè)HTTP狀態(tài)200和HTTP頭的內(nèi)容類型(content-type),使用 response.write() 函數(shù)在HTTP相應(yīng)主體中發(fā)送文本“Hello World"。

最后,我們調(diào)用 response.end() 完成響應(yīng)。

目前來說,我們對(duì)請(qǐng)求的細(xì)節(jié)并不在意,所以我們沒有使用 request 對(duì)象。

服務(wù)端的模塊放在哪里

OK,就像我保證過的那樣,我們現(xiàn)在可以回到我們?nèi)绾谓M織應(yīng)用這個(gè)問題上了。我們現(xiàn)在在 server.js 文件中有一個(gè)非?;A(chǔ)的HTTP服務(wù)器代碼,而且我提到通常我們會(huì)有一個(gè)叫 index.js 的文件去調(diào)用應(yīng)用的其他模塊(比如 server.js 中的HTTP服務(wù)器模塊)來引導(dǎo)和啟動(dòng)應(yīng)用。

我們現(xiàn)在就來談?wù)勗趺窗裺erver.js變成一個(gè)真正的Node.js模塊,使它可以被我們(還沒動(dòng)工)的 index.js 主文件使用。

也許你已經(jīng)注意到,我們已經(jīng)在代碼中使用了模塊了。像這樣:

復(fù)制代碼 代碼如下:

var http = require("http");

...

http.createServer(...);


Node.js中自帶了一個(gè)叫做“http”的模塊,我們?cè)谖覀兊拇a中請(qǐng)求它并把返回值賦給一個(gè)本地變量。

這把我們的本地變量變成了一個(gè)擁有所有 http 模塊所提供的公共方法的對(duì)象。

給這種本地變量起一個(gè)和模塊名稱一樣的名字是一種慣例,但是你也可以按照自己的喜好來:

復(fù)制代碼 代碼如下:

var foo = require("http");

...

foo.createServer(...);


很好,怎么使用Node.js內(nèi)部模塊已經(jīng)很清楚了。我們?cè)趺磩?chuàng)建自己的模塊,又怎么使用它呢?

等我們把 server.js 變成一個(gè)真正的模塊,你就能搞明白了。

事實(shí)上,我們不用做太多的修改。把某段代碼變成模塊意味著我們需要把我們希望提供其功能的部分 導(dǎo)出 到請(qǐng)求這個(gè)模塊的腳本。

目前,我們的HTTP服務(wù)器需要導(dǎo)出的功能非常簡(jiǎn)單,因?yàn)檎?qǐng)求服務(wù)器模塊的腳本僅僅是需要啟動(dòng)服務(wù)器而已。

我們把我們的服務(wù)器腳本放到一個(gè)叫做 start 的函數(shù)里,然后我們會(huì)導(dǎo)出這個(gè)函數(shù)。

復(fù)制代碼 代碼如下:

var http = require("http");

function start() {
  function onRequest(request, response) {
    console.log("Request received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


這樣,我們現(xiàn)在就可以創(chuàng)建我們的主文件 index.js 并在其中啟動(dòng)我們的HTTP了,雖然服務(wù)器的代碼還在 server.js 中。

創(chuàng)建 index.js 文件并寫入以下內(nèi)容:

復(fù)制代碼 代碼如下:

var server = require("./server");

server.start();


正如你所看到的,我們可以像使用任何其他的內(nèi)置模塊一樣使用server模塊:請(qǐng)求這個(gè)文件并把它指向一個(gè)變量,其中已導(dǎo)出的函數(shù)就可以被我們使用了。

好了。我們現(xiàn)在就可以從我們的主要腳本啟動(dòng)我們的的應(yīng)用了,而它還是老樣子:

復(fù)制代碼 代碼如下:

node index.js

非常好,我們現(xiàn)在可以把我們的應(yīng)用的不同部分放入不同的文件里,并且通過生成模塊的方式把它們連接到一起了。

我們?nèi)匀恢粨碛姓麄€(gè)應(yīng)用的最初部分:我們可以接收HTTP請(qǐng)求。但是我們得做點(diǎn)什么——對(duì)于不同的URL請(qǐng)求,服務(wù)器應(yīng)該有不同的反應(yīng)。

對(duì)于一個(gè)非常簡(jiǎn)單的應(yīng)用來說,你可以直接在回調(diào)函數(shù) onRequest() 中做這件事情。不過就像我說過的,我們應(yīng)該加入一些抽象的元素,讓我們的例子變得更有趣一點(diǎn)兒。

處理不同的HTTP請(qǐng)求在我們的代碼中是一個(gè)不同的部分,叫做“路由選擇”——那么,我們接下來就創(chuàng)造一個(gè)叫做 路由 的模塊吧。

如何來進(jìn)行請(qǐng)求的“路由”

我們要為路由提供請(qǐng)求的URL和其他需要的GET及POST參數(shù),隨后路由需要根據(jù)這些數(shù)據(jù)來執(zhí)行相應(yīng)的代碼(這里“代碼”對(duì)應(yīng)整個(gè)應(yīng)用的第三部分:一系列在接收到請(qǐng)求時(shí)真正工作的處理程序)。

因此,我們需要查看HTTP請(qǐng)求,從中提取出請(qǐng)求的URL以及GET/POST參數(shù)。這一功能應(yīng)當(dāng)屬于路由還是服務(wù)器(甚至作為一個(gè)模塊自身的功能)確實(shí)值得探討,但這里暫定其為我們的HTTP服務(wù)器的功能。

我們需要的所有數(shù)據(jù)都會(huì)包含在request對(duì)象中,該對(duì)象作為onRequest()回調(diào)函數(shù)的第一個(gè)參數(shù)傳遞。但是為了解析這些數(shù)據(jù),我們需要額外的Node.JS模塊,它們分別是url和querystring模塊。

復(fù)制代碼 代碼如下:

                               url.parse(string).query

           url.parse(string).pathname      |

                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----

                                 |          |
              querystring(string)["foo"]    |

                         querystring(string)["hello"]

當(dāng)然我們也可以用querystring模塊來解析POST請(qǐng)求體中的參數(shù),稍后會(huì)有演示。

現(xiàn)在我們來給onRequest()函數(shù)加上一些邏輯,用來找出瀏覽器請(qǐng)求的URL路徑:

var http = require("http");
var url = require("url");

function start() {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;
好了,我們的應(yīng)用現(xiàn)在可以通過請(qǐng)求的URL路徑來區(qū)別不同請(qǐng)求了--這使我們得以使用路由(還未完成)來將請(qǐng)求以URL路徑為基準(zhǔn)映射到處理程序上。

在我們所要構(gòu)建的應(yīng)用中,這意味著來自/start和/upload的請(qǐng)求可以使用不同的代碼來處理。稍后我們將看到這些內(nèi)容是如何整合到一起的。

現(xiàn)在我們可以來編寫路由了,建立一個(gè)名為router.js的文件,添加以下內(nèi)容:

function route(pathname) {
  console.log("About to route a request for " + pathname);
}

exports.route = route;
如你所見,這段代碼什么也沒干,不過對(duì)于現(xiàn)在來說這是應(yīng)該的。在添加更多的邏輯以前,我們先來看看如何把路由和服務(wù)器整合起來。

我們的服務(wù)器應(yīng)當(dāng)知道路由的存在并加以有效利用。我們當(dāng)然可以通過硬編碼的方式將這一依賴項(xiàng)綁定到服務(wù)器上,但是其它語(yǔ)言的編程經(jīng)驗(yàn)告訴我們這會(huì)是一件非常痛苦的事,因此我們將使用依賴注入的方式較松散地添加路由模塊(你可以讀讀Martin Fowlers關(guān)于依賴注入的大作來作為背景知識(shí))。

首先,我們來擴(kuò)展一下服務(wù)器的start()函數(shù),以便將路由函數(shù)作為參數(shù)傳遞過去:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(pathname);

    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


同時(shí),我們會(huì)相應(yīng)擴(kuò)展index.js,使得路由函數(shù)可以被注入到服務(wù)器中:
復(fù)制代碼 代碼如下:

var server = require("./server");
var router = require("./router");

server.start(router.route);


在這里,我們傳遞的函數(shù)依舊什么也沒做。

如果現(xiàn)在啟動(dòng)應(yīng)用(node index.js,始終記得這個(gè)命令行),隨后請(qǐng)求一個(gè)URL,你將會(huì)看到應(yīng)用輸出相應(yīng)的信息,這表明我們的HTTP服務(wù)器已經(jīng)在使用路由模塊了,并會(huì)將請(qǐng)求的路徑傳遞給路由:

復(fù)制代碼 代碼如下:

bash$ node index.js
Request for /foo received.
About to route a request for /foo

(以上輸出已經(jīng)去掉了比較煩人的/favicon.ico請(qǐng)求相關(guān)的部分)。

行為驅(qū)動(dòng)執(zhí)行

請(qǐng)?jiān)试S我再次脫離主題,在這里談一談函數(shù)式編程。

將函數(shù)作為參數(shù)傳遞并不僅僅出于技術(shù)上的考量。對(duì)軟件設(shè)計(jì)來說,這其實(shí)是個(gè)哲學(xué)問題。想想這樣的場(chǎng)景:在index文件中,我們可以將router對(duì)象傳遞進(jìn)去,服務(wù)器隨后可以調(diào)用這個(gè)對(duì)象的route函數(shù)。

就像這樣,我們傳遞一個(gè)東西,然后服務(wù)器利用這個(gè)東西來完成一些事。嗨那個(gè)叫路由的東西,能幫我把這個(gè)路由一下嗎?

但是服務(wù)器其實(shí)不需要這樣的東西。它只需要把事情做完就行,其實(shí)為了把事情做完,你根本不需要東西,你需要的是動(dòng)作。也就是說,你不需要名詞,你需要?jiǎng)釉~。

理解了這個(gè)概念里最核心、最基本的思想轉(zhuǎn)換后,我自然而然地理解了函數(shù)編程。

我是在讀了Steve Yegge的大作名詞王國(guó)中的死刑之后理解函數(shù)編程。你也去讀一讀這本書吧,真的。這是曾給予我閱讀的快樂的關(guān)于軟件的書籍之一。

路由給真正的請(qǐng)求處理程序

回到正題,現(xiàn)在我們的HTTP服務(wù)器和請(qǐng)求路由模塊已經(jīng)如我們的期望,可以相互交流了,就像一對(duì)親密無(wú)間的兄弟。

當(dāng)然這還遠(yuǎn)遠(yuǎn)不夠,路由,顧名思義,是指我們要針對(duì)不同的URL有不同的處理方式。例如處理/start的“業(yè)務(wù)邏輯”就應(yīng)該和處理/upload的不同。

在現(xiàn)在的實(shí)現(xiàn)下,路由過程會(huì)在路由模塊中“結(jié)束”,并且路由模塊并不是真正針對(duì)請(qǐng)求“采取行動(dòng)”的模塊,否則當(dāng)我們的應(yīng)用程序變得更為復(fù)雜時(shí),將無(wú)法很好地?cái)U(kuò)展。

我們暫時(shí)把作為路由目標(biāo)的函數(shù)稱為請(qǐng)求處理程序。現(xiàn)在我們不要急著來開發(fā)路由模塊,因?yàn)槿绻?qǐng)求處理程序沒有就緒的話,再怎么完善路由模塊也沒有多大意義。

應(yīng)用程序需要新的部件,因此加入新的模塊 -- 已經(jīng)無(wú)需為此感到新奇了。我們來創(chuàng)建一個(gè)叫做requestHandlers的模塊,并對(duì)于每一個(gè)請(qǐng)求處理程序,添加一個(gè)占位用函數(shù),隨后將這些函數(shù)作為模塊的方法導(dǎo)出:

復(fù)制代碼 代碼如下:

function start() {
  console.log("Request handler 'start' was called.");
}

function upload() {
  console.log("Request handler 'upload' was called.");
}

exports.start = start;
exports.upload = upload;


這樣我們就可以把請(qǐng)求處理程序和路由模塊連接起來,讓路由“有路可尋”。

在這里我們得做個(gè)決定:是將requestHandlers模塊硬編碼到路由里來使用,還是再添加一點(diǎn)依賴注入?雖然和其他模式一樣,依賴注入不應(yīng)該僅僅為使用而使用,但在現(xiàn)在這個(gè)情況下,使用依賴注入可以讓路由和請(qǐng)求處理程序之間的耦合更加松散,也因此能讓路由的重用性更高。

這意味著我們得將請(qǐng)求處理程序從服務(wù)器傳遞到路由中,但感覺上這么做更離譜了,我們得一路把這堆請(qǐng)求處理程序從我們的主文件傳遞到服務(wù)器中,再將之從服務(wù)器傳遞到路由。

那么我們要怎么傳遞這些請(qǐng)求處理程序呢?別看現(xiàn)在我們只有2個(gè)處理程序,在一個(gè)真實(shí)的應(yīng)用中,請(qǐng)求處理程序的數(shù)量會(huì)不斷增加,我們當(dāng)然不想每次有一個(gè)新的URL或請(qǐng)求處理程序時(shí),都要為了在路由里完成請(qǐng)求到處理程序的映射而反復(fù)折騰。除此之外,在路由里有一大堆if request == x then call handler y也使得系統(tǒng)丑陋不堪。

仔細(xì)想想,有一大堆東西,每個(gè)都要映射到一個(gè)字符串(就是請(qǐng)求的URL)上?似乎關(guān)聯(lián)數(shù)組(associative array)能完美勝任。

不過結(jié)果有點(diǎn)令人失望,JavaScript沒提供關(guān)聯(lián)數(shù)組 -- 也可以說它提供了?事實(shí)上,在JavaScript中,真正能提供此類功能的是它的對(duì)象。

在這方面,http://msdn.microsoft.com/en-us/magazine/cc163419.aspx有一個(gè)不錯(cuò)的介紹,我在此摘錄一段:

在C++或C#中,當(dāng)我們談到對(duì)象,指的是類或者結(jié)構(gòu)體的實(shí)例。對(duì)象根據(jù)他們實(shí)例化的模板(就是所謂的類),會(huì)擁有不同的屬性和方法。但在JavaScript里對(duì)象不是這個(gè)概念。在JavaScript中,對(duì)象就是一個(gè)鍵/值對(duì)的集合 -- 你可以把JavaScript的對(duì)象想象成一個(gè)鍵為字符串類型的字典。

但如果JavaScript的對(duì)象僅僅是鍵/值對(duì)的集合,它又怎么會(huì)擁有方法呢?好吧,這里的值可以是字符串、數(shù)字或者……函數(shù)!

好了,最后再回到代碼上來?,F(xiàn)在我們已經(jīng)確定將一系列請(qǐng)求處理程序通過一個(gè)對(duì)象來傳遞,并且需要使用松耦合的方式將這個(gè)對(duì)象注入到route()函數(shù)中。

我們先將這個(gè)對(duì)象引入到主文件index.js中:

復(fù)制代碼 代碼如下:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.start(router.route, handle);


雖然handle并不僅僅是一個(gè)“東西”(一些請(qǐng)求處理程序的集合),我還是建議以一個(gè)動(dòng)詞作為其命名,這樣做可以讓我們?cè)诼酚芍惺褂酶鲿车谋磉_(dá)式,稍后會(huì)有說明。

正如所見,將不同的URL映射到相同的請(qǐng)求處理程序上是很容易的:只要在對(duì)象中添加一個(gè)鍵為"/"的屬性,對(duì)應(yīng)requestHandlers.start即可,這樣我們就可以干凈簡(jiǎn)潔地配置/start和/的請(qǐng)求都交由start這一處理程序處理。

在完成了對(duì)象的定義后,我們把它作為額外的參數(shù)傳遞給服務(wù)器,為此將server.js修改如下:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname);

    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


這樣我們就在start()函數(shù)里添加了handle參數(shù),并且把handle對(duì)象作為第一個(gè)參數(shù)傳遞給了route()回調(diào)函數(shù)。

然后我們相應(yīng)地在route.js文件中修改route()函數(shù):

復(fù)制代碼 代碼如下:

function route(handle, pathname) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname]();
  } else {
    console.log("No request handler found for " + pathname);
  }
}

exports.route = route;


通過以上代碼,我們首先檢查給定的路徑對(duì)應(yīng)的請(qǐng)求處理程序是否存在,如果存在的話直接調(diào)用相應(yīng)的函數(shù)。我們可以用從關(guān)聯(lián)數(shù)組中獲取元素一樣的方式從傳遞的對(duì)象中獲取請(qǐng)求處理函數(shù),因此就有了簡(jiǎn)潔流暢的形如handle[pathname]();的表達(dá)式,這個(gè)感覺就像在前方中提到的那樣:“嗨,請(qǐng)幫我處理了這個(gè)路徑”。

有了這些,我們就把服務(wù)器、路由和請(qǐng)求處理程序在一起了?,F(xiàn)在我們啟動(dòng)應(yīng)用程序并在瀏覽器中訪問http://localhost:8888/start,以下日志可以說明系統(tǒng)調(diào)用了正確的請(qǐng)求處理程序:

復(fù)制代碼 代碼如下:

Server has started.
Request for /start received.
About to route a request for /start
Request handler 'start' was called.

并且在瀏覽器中打開http://localhost:8888/可以看到這個(gè)請(qǐng)求同樣被start請(qǐng)求處理程序處理了:
復(fù)制代碼 代碼如下:

Request for / received.
About to route a request for /
Request handler 'start' was called.

讓請(qǐng)求處理程序作出響應(yīng)

很好。不過現(xiàn)在要是請(qǐng)求處理程序能夠向?yàn)g覽器返回一些有意義的信息而并非全是“Hello World”,那就更好了。

這里要記住的是,瀏覽器發(fā)出請(qǐng)求后獲得并顯示的“Hello World”信息仍是來自于我們server.js文件中的onRequest函數(shù)。

其實(shí)“處理請(qǐng)求”說白了就是“對(duì)請(qǐng)求作出響應(yīng)”,因此,我們需要讓請(qǐng)求處理程序能夠像onRequest函數(shù)那樣可以和瀏覽器進(jìn)行“對(duì)話”。

不好的實(shí)現(xiàn)方式

對(duì)于我們這樣擁有PHP或者Ruby技術(shù)背景的開發(fā)者來說,最直截了當(dāng)?shù)膶?shí)現(xiàn)方式事實(shí)上并不是非??孔V: 看似有效,實(shí)則未必如此。

這里我指的“直截了當(dāng)?shù)膶?shí)現(xiàn)方式”意思是:讓請(qǐng)求處理程序通過onRequest函數(shù)直接返回(return())他們要展示給用戶的信息。

我們先就這樣去實(shí)現(xiàn),然后再來看為什么這不是一種很好的實(shí)現(xiàn)方式。

讓我們從讓請(qǐng)求處理程序返回需要在瀏覽器中顯示的信息開始。我們需要將requestHandler.js修改為如下形式:

復(fù)制代碼 代碼如下:

function start() {
  console.log("Request handler 'start' was called.");
  return "Hello Start";
}

function upload() {
  console.log("Request handler 'upload' was called.");
  return "Hello Upload";
}

exports.start = start;
exports.upload = upload;


好的。同樣的,請(qǐng)求路由需要將請(qǐng)求處理程序返回給它的信息返回給服務(wù)器。因此,我們需要將router.js修改為如下形式:
復(fù)制代碼 代碼如下:

function route(handle, pathname) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    return handle[pathname]();
  } else {
    console.log("No request handler found for " + pathname);
    return "404 Not found";
  }
}

exports.route = route;


正如上述代碼所示,當(dāng)請(qǐng)求無(wú)法路由的時(shí)候,我們也返回了一些相關(guān)的錯(cuò)誤信息。

最后,我們需要對(duì)我們的server.js進(jìn)行重構(gòu)以使得它能夠?qū)⒄?qǐng)求處理程序通過請(qǐng)求路由返回的內(nèi)容響應(yīng)給瀏覽器,如下所示:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    response.writeHead(200, {"Content-Type": "text/plain"});
    var content = route(handle, pathname)
    response.write(content);
    response.end();
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


如果我們運(yùn)行重構(gòu)后的應(yīng)用,一切都會(huì)工作的很好:請(qǐng)求http://localhost:8888/start,瀏覽器會(huì)輸出“Hello Start”,請(qǐng)求http://localhost:8888/upload會(huì)輸出“Hello Upload”,而請(qǐng)求http://localhost:8888/foo 會(huì)輸出“404 Not found”。

好,那么問題在哪里呢?簡(jiǎn)單的說就是: 當(dāng)未來有請(qǐng)求處理程序需要進(jìn)行非阻塞的操作的時(shí)候,我們的應(yīng)用就“掛”了。

沒理解?沒關(guān)系,下面就來詳細(xì)解釋下。

阻塞與非阻塞

正如此前所提到的,當(dāng)在請(qǐng)求處理程序中包括非阻塞操作時(shí)就會(huì)出問題。但是,在說這之前,我們先來看看什么是阻塞操作。

我不想去解釋“阻塞”和“非阻塞”的具體含義,我們直接來看,當(dāng)在請(qǐng)求處理程序中加入阻塞操作時(shí)會(huì)發(fā)生什么。

這里,我們來修改下start請(qǐng)求處理程序,我們讓它等待10秒以后再返回“Hello Start”。因?yàn)?,JavaScript中沒有類似sleep()這樣的操作,所以這里只能夠來點(diǎn)小Hack來模擬實(shí)現(xiàn)。

讓我們將requestHandlers.js修改成如下形式:

復(fù)制代碼 代碼如下:

function start() {
  console.log("Request handler 'start' was called.");

  function sleep(milliSeconds) {
    var startTime = new Date().getTime();
    while (new Date().getTime() < startTime + milliSeconds);
  }

  sleep(10000);
  return "Hello Start";
}

function upload() {
  console.log("Request handler 'upload' was called.");
  return "Hello Upload";
}

exports.start = start;
exports.upload = upload;


上述代碼中,當(dāng)函數(shù)start()被調(diào)用的時(shí)候,Node.js會(huì)先等待10秒,之后才會(huì)返回“Hello Start”。當(dāng)調(diào)用upload()的時(shí)候,會(huì)和此前一樣立即返回。

(當(dāng)然了,這里只是模擬休眠10秒,實(shí)際場(chǎng)景中,這樣的阻塞操作有很多,比方說一些長(zhǎng)時(shí)間的計(jì)算操作等。)

接下來就讓我們來看看,我們的改動(dòng)帶來了哪些變化。

如往常一樣,我們先要重啟下服務(wù)器。為了看到效果,我們要進(jìn)行一些相對(duì)復(fù)雜的操作(跟著我一起做): 首先,打開兩個(gè)瀏覽器窗口或者標(biāo)簽頁(yè)。在第一個(gè)瀏覽器窗口的地址欄中輸入http://localhost:8888/start, 但是先不要打開它!

在第二個(gè)瀏覽器窗口的地址欄中輸入http://localhost:8888/upload, 同樣的,先不要打開它!

接下來,做如下操作:在第一個(gè)窗口中(“/start”)按下回車,然后快速切換到第二個(gè)窗口中(“/upload”)按下回車。

注意,發(fā)生了什么: /start URL加載花了10秒,這和我們預(yù)期的一樣。但是,/upload URL居然也花了10秒,而它在對(duì)應(yīng)的請(qǐng)求處理程序中并沒有類似于sleep()這樣的操作!

這到底是為什么呢?原因就是start()包含了阻塞操作。形象的說就是“它阻塞了所有其他的處理工作”。

這顯然是個(gè)問題,因?yàn)镹ode一向是這樣來標(biāo)榜自己的:“在node中除了代碼,所有一切都是并行執(zhí)行的”。

這句話的意思是說,Node.js可以在不新增額外線程的情況下,依然可以對(duì)任務(wù)進(jìn)行并行處理 —— Node.js是單線程的。它通過事件輪詢(event loop)來實(shí)現(xiàn)并行操作,對(duì)此,我們應(yīng)該要充分利用這一點(diǎn) —— 盡可能的避免阻塞操作,取而代之,多使用非阻塞操作。

然而,要用非阻塞操作,我們需要使用回調(diào),通過將函數(shù)作為參數(shù)傳遞給其他需要花時(shí)間做處理的函數(shù)(比方說,休眠10秒,或者查詢數(shù)據(jù)庫(kù),又或者是進(jìn)行大量的計(jì)算)。

對(duì)于Node.js來說,它是這樣處理的:“嘿,probablyExpensiveFunction()(譯者注:這里指的就是需要花時(shí)間處理的函數(shù)),你繼續(xù)處理你的事情,我(Node.js線程)先不等你了,我繼續(xù)去處理你后面的代碼,請(qǐng)你提供一個(gè)callbackFunction(),等你處理完之后我會(huì)去調(diào)用該回調(diào)函數(shù)的,謝謝!”

(如果想要了解更多關(guān)于事件輪詢細(xì)節(jié),可以閱讀Mixu的博文——理解node.js的事件輪詢。)

接下來,我們會(huì)介紹一種錯(cuò)誤的使用非阻塞操作的方式。

和上次一樣,我們通過修改我們的應(yīng)用來暴露問題。

這次我們還是拿start請(qǐng)求處理程序來“開刀”。將其修改成如下形式:

復(fù)制代碼 代碼如下:

var exec = require("child_process").exec;

function start() {
  console.log("Request handler 'start' was called.");
  var content = "empty";

  exec("ls -lah", function (error, stdout, stderr) {
    content = stdout;
  });

  return content;
}

function upload() {
  console.log("Request handler 'upload' was called.");
  return "Hello Upload";
}

exports.start = start;
exports.upload = upload;


上述代碼中,我們引入了一個(gè)新的Node.js模塊,child_process。之所以用它,是為了實(shí)現(xiàn)一個(gè)既簡(jiǎn)單又實(shí)用的非阻塞操作:exec()。

exec()做了什么呢?它從Node.js來執(zhí)行一個(gè)shell命令。在上述例子中,我們用它來獲取當(dāng)前目錄下所有的文件(“l(fā)s -lah”),然后,當(dāng)/startURL請(qǐng)求的時(shí)候?qū)⑽募畔⑤敵龅綖g覽器中。

上述代碼是非常直觀的: 創(chuàng)建了一個(gè)新的變量content(初始值為“empty”),執(zhí)行“l(fā)s -lah”命令,將結(jié)果賦值給content,最后將content返回。

和往常一樣,我們啟動(dòng)服務(wù)器,然后訪問“http://localhost:8888/start” 。

之后會(huì)載入一個(gè)漂亮的web頁(yè)面,其內(nèi)容為“empty”。怎么回事?

這個(gè)時(shí)候,你可能大致已經(jīng)猜到了,exec()在非阻塞這塊發(fā)揮了神奇的功效。它其實(shí)是個(gè)很好的東西,有了它,我們可以執(zhí)行非常耗時(shí)的shell操作而無(wú)需迫使我們的應(yīng)用停下來等待該操作。

(如果想要證明這一點(diǎn),可以將“l(fā)s -lah”換成比如“find /”這樣更耗時(shí)的操作來效果)。

然而,針對(duì)瀏覽器顯示的結(jié)果來看,我們并不滿意我們的非阻塞操作,對(duì)吧?

好,接下來,我們來修正這個(gè)問題。在這過程中,讓我們先來看看為什么當(dāng)前的這種方式不起作用。

問題就在于,為了進(jìn)行非阻塞工作,exec()使用了回調(diào)函數(shù)。

在我們的例子中,該回調(diào)函數(shù)就是作為第二個(gè)參數(shù)傳遞給exec()的匿名函數(shù):

復(fù)制代碼 代碼如下:

function (error, stdout, stderr) {
  content = stdout;
}

現(xiàn)在就到了問題根源所在了:我們的代碼是同步執(zhí)行的,這就意味著在調(diào)用exec()之后,Node.js會(huì)立即執(zhí)行 return content ;在這個(gè)時(shí)候,content仍然是“empty”,因?yàn)閭鬟f給exec()的回調(diào)函數(shù)還未執(zhí)行到——因?yàn)閑xec()的操作是異步的。

我們這里“l(fā)s -lah”的操作其實(shí)是非??斓模ǔ钱?dāng)前目錄下有上百萬(wàn)個(gè)文件)。這也是為什么回調(diào)函數(shù)也會(huì)很快的執(zhí)行到 —— 不過,不管怎么說它還是異步的。

為了讓效果更加明顯,我們想象一個(gè)更耗時(shí)的命令: “find /”,它在我機(jī)器上需要執(zhí)行1分鐘左右的時(shí)間,然而,盡管在請(qǐng)求處理程序中,我把“l(fā)s -lah”換成“find /”,當(dāng)打開/start URL的時(shí)候,依然能夠立即獲得HTTP響應(yīng) —— 很明顯,當(dāng)exec()在后臺(tái)執(zhí)行的時(shí)候,Node.js自身會(huì)繼續(xù)執(zhí)行后面的代碼。并且我們這里假設(shè)傳遞給exec()的回調(diào)函數(shù),只會(huì)在“find /”命令執(zhí)行完成之后才會(huì)被調(diào)用。

那究竟我們要如何才能實(shí)現(xiàn)將當(dāng)前目錄下的文件列表顯示給用戶呢?

好,了解了這種不好的實(shí)現(xiàn)方式之后,我們接下來來介紹如何以正確的方式讓請(qǐng)求處理程序?qū)g覽器請(qǐng)求作出響應(yīng)。

以非阻塞操作進(jìn)行請(qǐng)求響應(yīng)

我剛剛提到了這樣一個(gè)短語(yǔ) —— “正確的方式”。而事實(shí)上通?!罢_的方式”一般都不簡(jiǎn)單。

不過,用Node.js就有這樣一種實(shí)現(xiàn)方案: 函數(shù)傳遞。下面就讓我們來具體看看如何實(shí)現(xiàn)。

到目前為止,我們的應(yīng)用已經(jīng)可以通過應(yīng)用各層之間傳遞值的方式(請(qǐng)求處理程序 -> 請(qǐng)求路由 -> 服務(wù)器)將請(qǐng)求處理程序返回的內(nèi)容(請(qǐng)求處理程序最終要顯示給用戶的內(nèi)容)傳遞給HTTP服務(wù)器。

現(xiàn)在我們采用如下這種新的實(shí)現(xiàn)方式:相對(duì)采用將內(nèi)容傳遞給服務(wù)器的方式,我們這次采用將服務(wù)器“傳遞”給內(nèi)容的方式。 從實(shí)踐角度來說,就是將response對(duì)象(從服務(wù)器的回調(diào)函數(shù)onRequest()獲?。┩ㄟ^請(qǐng)求路由傳遞給請(qǐng)求處理程序。 隨后,處理程序就可以采用該對(duì)象上的函數(shù)來對(duì)請(qǐng)求作出響應(yīng)。

原理就是如此,接下來讓我們來一步步實(shí)現(xiàn)這種方案。

先從server.js開始:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname, response);
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


相對(duì)此前從route()函數(shù)獲取返回值的做法,這次我們將response對(duì)象作為第三個(gè)參數(shù)傳遞給route()函數(shù),并且,我們將onRequest()處理程序中所有有關(guān)response的函數(shù)調(diào)都移除,因?yàn)槲覀兿M@部分工作讓route()函數(shù)來完成。

下面就來看看我們的router.js:

復(fù)制代碼 代碼如下:

function route(handle, pathname, response) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname](response);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;


同樣的模式:相對(duì)此前從請(qǐng)求處理程序中獲取返回值,這次取而代之的是直接傳遞response對(duì)象。

如果沒有對(duì)應(yīng)的請(qǐng)求處理器處理,我們就直接返回“404”錯(cuò)誤。

最后,我們將requestHandler.js修改為如下形式:

復(fù)制代碼 代碼如下:

var exec = require("child_process").exec;

function start(response) {
  console.log("Request handler 'start' was called.");

  exec("ls -lah", function (error, stdout, stderr) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write(stdout);
    response.end();
  });
}

function upload(response) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello Upload");
  response.end();
}

exports.start = start;
exports.upload = upload;


我們的處理程序函數(shù)需要接收response參數(shù),為了對(duì)請(qǐng)求作出直接的響應(yīng)。

start處理程序在exec()的匿名回調(diào)函數(shù)中做請(qǐng)求響應(yīng)的操作,而upload處理程序仍然是簡(jiǎn)單的回復(fù)“Hello World”,只是這次是使用response對(duì)象而已。

這時(shí)再次我們啟動(dòng)應(yīng)用(node index.js),一切都會(huì)工作的很好。

如果想要證明/start處理程序中耗時(shí)的操作不會(huì)阻塞對(duì)/upload請(qǐng)求作出立即響應(yīng)的話,可以將requestHandlers.js修改為如下形式:

復(fù)制代碼 代碼如下:

var exec = require("child_process").exec;

function start(response) {
  console.log("Request handler 'start' was called.");

  exec("find /",
    { timeout: 10000, maxBuffer: 20000*1024 },
    function (error, stdout, stderr) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.write(stdout);
      response.end();
    });
}

function upload(response) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello Upload");
  response.end();
}

exports.start = start;
exports.upload = upload;


這樣一來,當(dāng)請(qǐng)求http://localhost:8888/start的時(shí)候,會(huì)花10秒鐘的時(shí)間才載入,而當(dāng)請(qǐng)求http://localhost:8888/upload的時(shí)候,會(huì)立即響應(yīng),縱然這個(gè)時(shí)候/start響應(yīng)還在處理中。

更有用的場(chǎng)景

到目前為止,我們做的已經(jīng)很好了,但是,我們的應(yīng)用沒有實(shí)際用途。

服務(wù)器,請(qǐng)求路由以及請(qǐng)求處理程序都已經(jīng)完成了,下面讓我們按照此前的用例給網(wǎng)站添加交互:用戶選擇一個(gè)文件,上傳該文件,然后在瀏覽器中看到上傳的文件。 為了保持簡(jiǎn)單,我們假設(shè)用戶只會(huì)上傳圖片,然后我們應(yīng)用將該圖片顯示到瀏覽器中。

好,下面就一步步來實(shí)現(xiàn),鑒于此前已經(jīng)對(duì)JavaScript原理性技術(shù)性的內(nèi)容做過大量介紹了,這次我們加快點(diǎn)速度。

要實(shí)現(xiàn)該功能,分為如下兩步: 首先,讓我們來看看如何處理POST請(qǐng)求(非文件上傳),之后,我們使用Node.js的一個(gè)用于文件上傳的外部模塊。之所以采用這種實(shí)現(xiàn)方式有兩個(gè)理由。

第一,盡管在Node.js中處理基礎(chǔ)的POST請(qǐng)求相對(duì)比較簡(jiǎn)單,但在這過程中還是能學(xué)到很多。
第二,用Node.js來處理文件上傳(multipart POST請(qǐng)求)是比較復(fù)雜的,它不在本書的范疇,但,如何使用外部模塊卻是在本書涉獵內(nèi)容之內(nèi)。

處理POST請(qǐng)求

考慮這樣一個(gè)簡(jiǎn)單的例子:我們顯示一個(gè)文本區(qū)(textarea)供用戶輸入內(nèi)容,然后通過POST請(qǐng)求提交給服務(wù)器。最后,服務(wù)器接受到請(qǐng)求,通過處理程序?qū)⑤斎氲膬?nèi)容展示到瀏覽器中。

/start請(qǐng)求處理程序用于生成帶文本區(qū)的表單,因此,我們將requestHandlers.js修改為如下形式:

function start(response) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello Upload");
  response.end();
}

exports.start = start;
exports.upload = upload;
好了,現(xiàn)在我們的應(yīng)用已經(jīng)很完善了,都可以獲得威比獎(jiǎng)(Webby Awards)了,哈哈。(譯者注:威比獎(jiǎng)是由國(guó)際數(shù)字藝術(shù)與科學(xué)學(xué)院主辦的評(píng)選全球最佳網(wǎng)站的獎(jiǎng)項(xiàng),具體參見詳細(xì)說明)通過在瀏覽器中訪問http://localhost:8888/start就可以看到簡(jiǎn)單的表單了,要記得重啟服務(wù)器哦!

你可能會(huì)說:這種直接將視覺元素放在請(qǐng)求處理程序中的方式太丑陋了。說的沒錯(cuò),但是,我并不想在本書中介紹諸如MVC之類的模式,因?yàn)檫@對(duì)于你了解JavaScript或者Node.js環(huán)境來說沒多大關(guān)系。

余下的篇幅,我們來探討一個(gè)更有趣的問題: 當(dāng)用戶提交表單時(shí),觸發(fā)/upload請(qǐng)求處理程序處理POST請(qǐng)求的問題。

現(xiàn)在,我們已經(jīng)是新手中的專家了,很自然會(huì)想到采用異步回調(diào)來實(shí)現(xiàn)非阻塞地處理POST請(qǐng)求的數(shù)據(jù)。

這里采用非阻塞方式處理是明智的,因?yàn)镻OST請(qǐng)求一般都比較“重” —— 用戶可能會(huì)輸入大量的內(nèi)容。用阻塞的方式處理大數(shù)據(jù)量的請(qǐng)求必然會(huì)導(dǎo)致用戶操作的阻塞。

為了使整個(gè)過程非阻塞,Node.js會(huì)將POST數(shù)據(jù)拆分成很多小的數(shù)據(jù)塊,然后通過觸發(fā)特定的事件,將這些小數(shù)據(jù)塊傳遞給回調(diào)函數(shù)。這里的特定的事件有data事件(表示新的小數(shù)據(jù)塊到達(dá)了)以及end事件(表示所有的數(shù)據(jù)都已經(jīng)接收完畢)。

我們需要告訴Node.js當(dāng)這些事件觸發(fā)的時(shí)候,回調(diào)哪些函數(shù)。怎么告訴呢? 我們通過在request對(duì)象上注冊(cè)監(jiān)聽器實(shí)現(xiàn)。這里的request對(duì)象是每次接收到HTTP請(qǐng)求時(shí)候,都會(huì)把該對(duì)象傳遞給onRequest回調(diào)函數(shù)。
如下所示:

復(fù)制代碼 代碼如下:

request.addListener("data", function(chunk) {
  // called when a new chunk of data was received
});

request.addListener("end", function() {
  // called when all chunks of data have been received
});


問題來了,這部分邏輯寫在哪里呢? 我們現(xiàn)在只是在服務(wù)器中獲取到了request對(duì)象 —— 我們并沒有像之前response對(duì)象那樣,把 request 對(duì)象傳遞給請(qǐng)求路由和請(qǐng)求處理程序。

在我看來,獲取所有來自請(qǐng)求的數(shù)據(jù),然后將這些數(shù)據(jù)給應(yīng)用層處理,應(yīng)該是HTTP服務(wù)器要做的事情。因此,我建議,我們直接在服務(wù)器中處理POST數(shù)據(jù),然后將最終的數(shù)據(jù)傳遞給請(qǐng)求路由和請(qǐng)求處理器,讓他們來進(jìn)行進(jìn)一步的處理。

因此,實(shí)現(xiàn)思路就是: 將data和end事件的回調(diào)函數(shù)直接放在服務(wù)器中,在data事件回調(diào)中收集所有的POST數(shù)據(jù),當(dāng)接收到所有數(shù)據(jù),觸發(fā)end事件后,其回調(diào)函數(shù)調(diào)用請(qǐng)求路由,并將數(shù)據(jù)傳遞給它,然后,請(qǐng)求路由再將該數(shù)據(jù)傳遞給請(qǐng)求處理程序。

還等什么,馬上來實(shí)現(xiàn)。先從server.js開始:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var postData = "";
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    request.setEncoding("utf8");

    request.addListener("data", function(postDataChunk) {
      postData += postDataChunk;
      console.log("Received POST data chunk '"+
      postDataChunk + "'.");
    });

    request.addListener("end", function() {
      route(handle, pathname, response, postData);
    });

  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;


上述代碼做了三件事情: 首先,我們?cè)O(shè)置了接收數(shù)據(jù)的編碼格式為UTF-8,然后注冊(cè)了“data”事件的監(jiān)聽器,用于收集每次接收到的新數(shù)據(jù)塊,并將其賦值給postData 變量,最后,我們將請(qǐng)求路由的調(diào)用移到end事件處理程序中,以確保它只會(huì)當(dāng)所有數(shù)據(jù)接收完畢后才觸發(fā),并且只觸發(fā)一次。我們同時(shí)還把POST數(shù)據(jù)傳遞給請(qǐng)求路由,因?yàn)檫@些數(shù)據(jù),請(qǐng)求處理程序會(huì)用到。

上述代碼在每個(gè)數(shù)據(jù)塊到達(dá)的時(shí)候輸出了日志,這對(duì)于最終生產(chǎn)環(huán)境來說,是很不好的(數(shù)據(jù)量可能會(huì)很大,還記得吧?),但是,在開發(fā)階段是很有用的,有助于讓我們看到發(fā)生了什么。

我建議可以嘗試下,嘗試著去輸入一小段文本,以及大段內(nèi)容,當(dāng)大段內(nèi)容的時(shí)候,就會(huì)發(fā)現(xiàn)data事件會(huì)觸發(fā)多次。

再來點(diǎn)酷的。我們接下來在/upload頁(yè)面,展示用戶輸入的內(nèi)容。要實(shí)現(xiàn)該功能,我們需要將postData傳遞給請(qǐng)求處理程序,修改router.js為如下形式:

復(fù)制代碼 代碼如下:

function route(handle, pathname, response, postData) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname](response, postData);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;


然后,在requestHandlers.js中,我們將數(shù)據(jù)包含在對(duì)upload請(qǐng)求的響應(yīng)中:
復(fù)制代碼 代碼如下:

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent: " + postData);
  response.end();
}

exports.start = start;
exports.upload = upload;


好了,我們現(xiàn)在可以接收POST數(shù)據(jù)并在請(qǐng)求處理程序中處理該數(shù)據(jù)了。

我們最后要做的是: 當(dāng)前我們是把請(qǐng)求的整個(gè)消息體傳遞給了請(qǐng)求路由和請(qǐng)求處理程序。我們應(yīng)該只把POST數(shù)據(jù)中,我們感興趣的部分傳遞給請(qǐng)求路由和請(qǐng)求處理程序。在我們這個(gè)例子中,我們感興趣的其實(shí)只是text字段。

我們可以使用此前介紹過的querystring模塊來實(shí)現(xiàn):

復(fù)制代碼 代碼如下:

var querystring = require("querystring");

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent the text: "+
  querystring.parse(postData).text);
  response.end();
}

exports.start = start;
exports.upload = upload;


好了,以上就是關(guān)于處理POST數(shù)據(jù)的全部?jī)?nèi)容。

處理文件上傳

最后,我們來實(shí)現(xiàn)我們最終的用例:允許用戶上傳圖片,并將該圖片在瀏覽器中顯示出來。

回到90年代,這個(gè)用例完全可以滿足用于IPO的商業(yè)模型了,如今,我們通過它能學(xué)到這樣兩件事情: 如何安裝外部Node.js模塊,以及如何將它們應(yīng)用到我們的應(yīng)用中。

這里我們要用到的外部模塊是Felix Geisendörfer開發(fā)的node-formidable模塊。它對(duì)解析上傳的文件數(shù)據(jù)做了很好的抽象。 其實(shí)說白了,處理文件上傳“就是”處理POST數(shù)據(jù) —— 但是,麻煩的是在具體的處理細(xì)節(jié),所以,這里采用現(xiàn)成的方案更合適點(diǎn)。

使用該模塊,首先需要安裝該模塊。Node.js有它自己的包管理器,叫NPM。它可以讓安裝Node.js的外部模塊變得非常方便。通過如下一條命令就可以完成該模塊的安裝:

復(fù)制代碼 代碼如下:

npm install formidable

如果終端輸出如下內(nèi)容:
復(fù)制代碼 代碼如下:

npm info build Success: formidable@1.0.9
npm ok

就說明模塊已經(jīng)安裝成功了。

現(xiàn)在我們就可以用formidable模塊了——使用外部模塊與內(nèi)部模塊類似,用require語(yǔ)句將其引入即可:

復(fù)制代碼 代碼如下:

var formidable = require("formidable");

這里該模塊做的就是將通過HTTP POST請(qǐng)求提交的表單,在Node.js中可以被解析。我們要做的就是創(chuàng)建一個(gè)新的IncomingForm,它是對(duì)提交表單的抽象表示,之后,就可以用它解析request對(duì)象,獲取表單中需要的數(shù)據(jù)字段。

node-formidable官方的例子展示了這兩部分是如何融合在一起工作的:

復(fù)制代碼 代碼如下:

var formidable = require('formidable'),
    http = require('http'),
    sys = require('sys');

http.createServer(function(req, res) {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    // parse a file upload
    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files) {
      res.writeHead(200, {'content-type': 'text/plain'});
      res.write('received upload:\n\n');
      res.end(sys.inspect({fields: fields, files: files}));
    });
    return;
  }

  // show a file upload form
  res.writeHead(200, {'content-type': 'text/html'});
  res.end(
    '<form action="/upload" enctype="multipart/form-data" '+
    'method="post">'+
    '<input type="text" name="title"><br>'+
    '<input type="file" name="upload" multiple="multiple"><br>'+
    '<input type="submit" value="Upload">'+
    '</form>'
  );
}).listen(8888);


如果我們將上述代碼,保存到一個(gè)文件中,并通過node來執(zhí)行,就可以進(jìn)行簡(jiǎn)單的表單提交了,包括文件上傳。然后,可以看到通過調(diào)用form.parse傳遞給回調(diào)函數(shù)的files對(duì)象的內(nèi)容,如下所示:
復(fù)制代碼 代碼如下:

received upload:

{ fields: { title: 'Hello World' },
  files:
   { upload:
      { size: 1558,
        path: '/tmp/1c747974a27a6292743669e91f29350b',
        name: 'us-flag.png',
        type: 'image/png',
        lastModifiedDate: Tue, 21 Jun 2011 07:02:41 GMT,
        _writeStream: [Object],
        length: [Getter],
        filename: [Getter],
        mime: [Getter] } } }


為了實(shí)現(xiàn)我們的功能,我們需要將上述代碼應(yīng)用到我們的應(yīng)用中,另外,我們還要考慮如何將上傳文件的內(nèi)容(保存在/tmp目錄中)顯示到瀏覽器中。

我們先來解決后面那個(gè)問題: 對(duì)于保存在本地硬盤中的文件,如何才能在瀏覽器中看到呢?

顯然,我們需要將該文件讀取到我們的服務(wù)器中,使用一個(gè)叫fs的模塊。

我們來添加/showURL的請(qǐng)求處理程序,該處理程序直接硬編碼將文件/tmp/test.png內(nèi)容展示到瀏覽器中。當(dāng)然了,首先需要將該圖片保存到這個(gè)位置才行。

將requestHandlers.js修改為如下形式:

復(fù)制代碼 代碼如下:

var querystring = require("querystring"),
    fs = require("fs");

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" '+
    'content="text/html; charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" method="post">'+
    '<textarea name="text" rows="20" cols="60"></textarea>'+
    '<input type="submit" value="Submit text" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent the text: "+
  querystring.parse(postData).text);
  response.end();
}

function show(response, postData) {
  console.log("Request handler 'show' was called.");
  fs.readFile("/tmp/test.png", "binary", function(error, file) {
    if(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.write(error + "\n");
      response.end();
    } else {
      response.writeHead(200, {"Content-Type": "image/png"});
      response.write(file, "binary");
      response.end();
    }
  });
}

exports.start = start;
exports.upload = upload;
exports.show = show;


我們還需要將這新的請(qǐng)求處理程序,添加到index.js中的路由映射表中:
復(fù)制代碼 代碼如下:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;

server.start(router.route, handle);


重啟服務(wù)器之后,通過訪問http://localhost:8888/show,就可以看到保存在/tmp/test.png的圖片了。

好,最后我們要的就是:

在/start表單中添加一個(gè)文件上傳元素
將node-formidable整合到我們的upload請(qǐng)求處理程序中,用于將上傳的圖片保存到/tmp/test.png
將上傳的圖片內(nèi)嵌到/uploadURL輸出的HTML中
第一項(xiàng)很簡(jiǎn)單。只需要在HTML表單中,添加一個(gè)multipart/form-data的編碼類型,移除此前的文本區(qū),添加一個(gè)文件上傳組件,并將提交按鈕的文案改為“Upload file”即可。 如下requestHandler.js所示:

復(fù)制代碼 代碼如下:

var querystring = require("querystring"),
    fs = require("fs");

function start(response, postData) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" '+
    'content="text/html; charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" enctype="multipart/form-data" '+
    'method="post">'+
    '<input type="file" name="upload">'+
    '<input type="submit" value="Upload file" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, postData) {
  console.log("Request handler 'upload' was called.");
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("You've sent the text: "+
  querystring.parse(postData).text);
  response.end();
}

function show(response, postData) {
  console.log("Request handler 'show' was called.");
  fs.readFile("/tmp/test.png", "binary", function(error, file) {
    if(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.write(error + "\n");
      response.end();
    } else {
      response.writeHead(200, {"Content-Type": "image/png"});
      response.write(file, "binary");
      response.end();
    }
  });
}

exports.start = start;
exports.upload = upload;
exports.show = show;


很好。下一步相對(duì)比較復(fù)雜。這里有這樣一個(gè)問題: 我們需要在upload處理程序中對(duì)上傳的文件進(jìn)行處理,這樣的話,我們就需要將request對(duì)象傳遞給node-formidable的form.parse函數(shù)。

但是,我們有的只是response對(duì)象和postData數(shù)組??礃幼?,我們只能不得不將request對(duì)象從服務(wù)器開始一路通過請(qǐng)求路由,再傳遞給請(qǐng)求處理程序。 或許還有更好的方案,但是,不管怎么說,目前這樣做可以滿足我們的需求。

到這里,我們可以將postData從服務(wù)器以及請(qǐng)求處理程序中移除了 —— 一方面,對(duì)于我們處理文件上傳來說已經(jīng)不需要了,另外一方面,它甚至可能會(huì)引發(fā)這樣一個(gè)問題: 我們已經(jīng)“消耗”了request對(duì)象中的數(shù)據(jù),這意味著,對(duì)于form.parse來說,當(dāng)它想要獲取數(shù)據(jù)的時(shí)候就什么也獲取不到了。(因?yàn)镹ode.js不會(huì)對(duì)數(shù)據(jù)做緩存)

我們從server.js開始 —— 移除對(duì)postData的處理以及request.setEncoding (這部分node-formidable自身會(huì)處理),轉(zhuǎn)而采用將request對(duì)象傳遞給請(qǐng)求路由的方式:

復(fù)制代碼 代碼如下:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");
    route(handle, pathname, response, request);
  }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;
接下來是 router.js —— 我們不再需要傳遞postData了,這次要傳遞request對(duì)象:

function route(handle, pathname, response, request) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname](response, request);
  } else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/html"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;


現(xiàn)在,request對(duì)象就可以在我們的upload請(qǐng)求處理程序中使用了。node-formidable會(huì)處理將上傳的文件保存到本地/tmp目錄中,而我們需要做的是確保該文件保存成/tmp/test.png。 沒錯(cuò),我們保持簡(jiǎn)單,并假設(shè)只允許上傳PNG圖片。

這里采用fs.renameSync(path1,path2)來實(shí)現(xiàn)。要注意的是,正如其名,該方法是同步執(zhí)行的, 也就是說,如果該重命名的操作很耗時(shí)的話會(huì)阻塞。 這塊我們先不考慮。

接下來,我們把處理文件上傳以及重命名的操作放到一起,如下requestHandlers.js所示:

復(fù)制代碼 代碼如下:

var querystring = require("querystring"),
    fs = require("fs"),
    formidable = require("formidable");

function start(response) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<form action="/upload" enctype="multipart/form-data" '+
    'method="post">'+
    '<input type="file" name="upload" multiple="multiple">'+
    '<input type="submit" value="Upload file" />'+
    '</form>'+
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response, request) {
  console.log("Request handler 'upload' was called.");

  var form = new formidable.IncomingForm();
  console.log("about to parse");
  form.parse(request, function(error, fields, files) {
    console.log("parsing done");
    fs.renameSync(files.upload.path, "/tmp/test.png");
    response.writeHead(200, {"Content-Type": "text/html"});
    response.write("received image:<br/>");
    response.write("<img src='/show' />");
    response.end();
  });
}

function show(response) {
  console.log("Request handler 'show' was called.");
  fs.readFile("/tmp/test.png", "binary", function(error, file) {
    if(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.write(error + "\n");
      response.end();
    } else {
      response.writeHead(200, {"Content-Type": "image/png"});
      response.write(file, "binary");
      response.end();
    }
  });
}

exports.start = start;
exports.upload = upload;
exports.show = show;


好了,重啟服務(wù)器,我們應(yīng)用所有的功能就可以用了。選擇一張本地圖片,將其上傳到服務(wù)器,然后瀏覽器就會(huì)顯示該圖片。

總結(jié)與展望

恭喜,我們的任務(wù)已經(jīng)完成了!我們開發(fā)完了一個(gè)Node.js的web應(yīng)用,應(yīng)用雖小,但卻“五臟俱全”。 期間,我們介紹了很多技術(shù)點(diǎn):服務(wù)端JavaScript、函數(shù)式編程、阻塞與非阻塞、回調(diào)、事件、內(nèi)部和外部模塊等等。

當(dāng)然了,還有許多本書沒有介紹到的: 如何操作數(shù)據(jù)庫(kù)、如何進(jìn)行單元測(cè)試、如何開發(fā)Node.js的外部模塊以及一些簡(jiǎn)單的諸如如何獲取GET請(qǐng)求之類的方法。

但本書畢竟只是一本給初學(xué)者的教程 —— 不可能覆蓋到所有的內(nèi)容。

幸運(yùn)的是,Node.js社區(qū)非?;钴S(作個(gè)不恰當(dāng)?shù)谋扔骶褪仟q如一群有多動(dòng)癥小孩子在一起,能不活躍嗎?), 這意味著,有許多關(guān)于Node.js的資源,有什么問題都可以向社區(qū)尋求解答。 其中Node.js社區(qū)的wiki以及 NodeCloud就是最好的資源。

相關(guān)文章

最新評(píng)論

岛国免费大片在线观看| 亚洲 欧美 精品 激情 偷拍| 好吊操视频这里只有精品| 亚洲高清免费在线观看视频| av手机在线免费观看日韩av| 亚洲精品亚洲人成在线导航| 夜女神免费福利视频| 51精品视频免费在线观看| 国产欧美日韩在线观看不卡| 亚洲天堂精品福利成人av| 亚洲av午夜免费观看| 久久人人做人人妻人人玩精品vr| 18禁网站一区二区三区四区 | 久久www免费人成一看片| 久久这里只有精品热视频| 国产视频精品资源网站| 亚洲国产精品美女在线观看| 天天操天天弄天天射| 青青青国产免费视频| 快点插进来操我逼啊视频| 香港一级特黄大片在线播放| 免费在线黄色观看网站| 日韩一区二区电国产精品| 国产综合视频在线看片| 一色桃子人妻一区二区三区| 人妻最新视频在线免费观看| 最新欧美一二三视频| 日本少妇精品免费视频| aⅴ五十路av熟女中出| 91国内视频在线观看| 亚洲人妻30pwc| 十八禁在线观看地址免费| 偷拍自拍福利视频在线观看| 欧美成人精品在线观看| 天堂v男人视频在线观看| 91亚洲国产成人精品性色| 69精品视频一区二区在线观看| 中文字幕奴隷色的舞台50| 88成人免费av网站| 精品国产污污免费网站入口自| 一区二区三区久久久91| 狠狠躁夜夜躁人人爽天天久天啪| 午夜久久久久久久99| 精品老妇女久久9g国产| 午夜大尺度无码福利视频| 亚洲av香蕉一区区二区三区犇| 91九色国产熟女一区二区| 日韩精品二区一区久久| 亚洲va国产va欧美精品88| 干逼又爽又黄又免费的视频| 日本后入视频在线观看| 久久机热/这里只有| 中文字幕无码日韩专区免费| 大香蕉大香蕉在线看| 99久久99一区二区三区| 岛国黄色大片在线观看| 欧美女同性恋免费a| 午夜精品福利一区二区三区p| 人妻在线精品录音叫床| 亚洲一区二区三区五区| 欧美一级视频一区二区| 精品国产乱码一区二区三区乱| 狠狠鲁狠狠操天天晚上干干| 最新日韩av传媒在线| 一区二区三区美女毛片| 午夜在线精品偷拍一区二| 国产乱子伦一二三区| 91色网站免费在线观看| 欧美特色aaa大片| 东京热男人的av天堂| 日本一二三中文字幕| 午夜精品九一唐人麻豆嫩草成人| 在线观看视频 你懂的| 久青青草视频手机在线免费观看 | 黑人进入丰满少妇视频| 91精品国产综合久久久蜜| 精品美女福利在线观看| 天天爽夜夜爽人人爽QC| 伊人综合aⅴ在线网| 亚洲高清国产一区二区三区| 成人av亚洲一区二区| 亚洲va国产va欧美va在线| 在线制服丝袜中文字幕| 亚洲 图片 欧美 图片| 80电影天堂网官网| 18禁美女无遮挡免费| 超污视频在线观看污污污 | 国产精品人妻熟女毛片av久| 国产亚洲欧美45p| 亚洲丝袜老师诱惑在线观看| 九一传媒制片厂视频在线免费观看 | 国产91久久精品一区二区字幕| 欧美美女人体视频一区| 一区二区熟女人妻视频| 1000部国产精品成人观看视频| 狠狠的往里顶撞h百合| 精品首页在线观看视频| 毛片一级完整版免费| 午夜婷婷在线观看视频| 亚洲伊人久久精品影院一美女洗澡 | 久久久久久97三级| 亚洲一区av中文字幕在线观看| 粉嫩av蜜乳av蜜臀 | 干逼又爽又黄又免费的视频| 只有精品亚洲视频在线观看| 欧美少妇性一区二区三区| 馒头大胆亚洲一区二区| 成人av电影免费版| 欧美另类一区二区视频| 老司机在线精品福利视频| 亚洲国产精品久久久久蜜桃| 国际av大片在线免费观看| 91社福利《在线观看| 中文字幕在线视频一区二区三区| 五月婷婷在线观看视频免费| 天天插天天狠天天操| 亚洲一区二区久久久人妻| 绝色少妇高潮3在线观看| 极品丝袜一区二区三区| 天天插天天色天天日| aⅴ五十路av熟女中出| 视频在线亚洲一区二区| 亚洲无码一区在线影院| 93人妻人人揉人人澡人人| 91国内精品自线在拍白富美| 久久久久久99国产精品| 久久精品久久精品亚洲人| 亚洲日本一区二区三区| 国产a级毛久久久久精品| 日比视频老公慢点好舒服啊| 夜鲁夜鲁狠鲁天天在线| 亚洲麻豆一区二区三区| 成年人免费看在线视频| 91免费放福利在线观看| 91 亚洲视频在线观看| 亚洲 色图 偷拍 欧美| 美女吃鸡巴操逼高潮视频| 久久农村老妇乱69系列| 亚洲国产成人av在线一区| 黄色黄色黄片78在线| 日日夜夜精品一二三| 免费成人av中文字幕| 亚洲美女自偷自拍11页| 亚洲2021av天堂| 亚洲男人的天堂a在线| 亚洲精品av在线观看| 夏目彩春在线中文字幕| 亚洲精品国产在线电影| 亚洲成高清a人片在线观看| 欧亚日韩一区二区三区观看视频 | 亚洲欧美久久久久久久久| 好了av中文字幕在线| 亚洲精品国偷自产在线观看蜜桃| 黄色在线观看免费观看在线| 中文字幕国产专区欧美激情| 91福利在线视频免费观看| 国产成人自拍视频在线免费观看| 国产精品国色综合久久| 亚洲最大免费在线观看| 被大鸡吧操的好舒服视频免费| 性感美女诱惑福利视频| 天美传媒mv视频在线观看| 亚洲免费视频欧洲免费视频| 日本xx片在线观看| 亚洲熟女女同志女同| 欧美一区二区三区乱码在线播放| 日本一区精品视频在线观看| 最近中文2019年在线看| 黑人3p华裔熟女普通话| 国产成人精品福利短视频| 午夜dv内射一区区| 亚洲男人的天堂a在线| 久久久久久99国产精品| 日韩黄色片在线观看网站| 夜夜骑夜夜操夜夜奸| 91成人精品亚洲国产| 中文字幕人妻av在线观看| 强行扒开双腿猛烈进入免费版| 国产在线一区二区三区麻酥酥| 黄工厂精品视频在线观看| www日韩a级s片av| 91精品免费久久久久久| 日日摸夜夜添夜夜添毛片性色av| 天天艹天天干天天操| 超级碰碰在线视频免费观看| 免费在线看的黄网站| 午夜成午夜成年片在线观看| 熟女视频一区,二区,三区| 日本人妻欲求不满中文字幕| 97青青青手机在线视频| 免费成人va在线观看| 欧美熟妇一区二区三区仙踪林| 超碰在线观看免费在线观看| 最新91精品视频在线| okirakuhuhu在线观看| 国产精品一区二区av国| 日韩剧情片电影在线收看| 老鸭窝在线观看一区| 午夜精品久久久久久99热| 欧美老妇精品另类不卡片| 青青青爽视频在线播放| 岛国毛片视频免费在线观看| 国产亚洲精品欧洲在线观看| 93人妻人人揉人人澡人人| 淫秽激情视频免费观看| 亚洲av无硬久久精品蜜桃| 日韩三级电影华丽的外出| 可以在线观看的av中文字幕| 日本少妇人妻xxxxx18| 经典av尤物一区二区| 色97视频在线播放| 亚洲午夜高清在线观看| 国产伦精品一区二区三区竹菊| 熟女人妻在线观看视频| av中文字幕网址在线| 亚洲国产欧美一区二区三区…| okirakuhuhu在线观看| 99精品视频之69精品视频 | 天天色天天爱天天爽| 青青擦在线视频国产在线| 国产91精品拍在线观看| 777奇米久久精品一区| 国产精品久久久黄网站| 午夜婷婷在线观看视频| 超碰97人人澡人人| 2022精品久久久久久中文字幕| 视频在线亚洲一区二区| 韩国三级aaaaa高清视频 | 午夜极品美女福利视频| 成人H精品动漫在线无码播放| 亚洲中文精品字幕在线观看| 五月天色婷婷在线观看视频免费| 久久久久五月天丁香社区| 欧美日韩精品永久免费网址| okirakuhuhu在线观看| 国产高清精品一区二区三区| 国际av大片在线免费观看| 亚洲熟妇无码一区二区三区| 特黄老太婆aa毛毛片| 自拍偷拍亚洲另类色图| 天天日天天操天天摸天天舔| 91精品国产黑色丝袜| 人人妻人人爽人人添夜| 国内资源最丰富的网站| 天天操天天爽天天干| 好吊视频—区二区三区| 色天天天天射天天舔| 97资源人妻免费在线视频| 亚洲中文字幕综合小综合| 日本黄色特一级视频| 精品乱子伦一区二区三区免费播| 精产国品久久一二三产区区别| 宅男噜噜噜666国产| 亚洲欧美精品综合图片小说| 亚洲欧美国产综合777| 成人福利视频免费在线| 蜜臀av久久久久蜜臀av麻豆| 天天日天天舔天天射进去| 国产综合精品久久久久蜜臀| 91精品国产高清自在线看香蕉网| 水蜜桃国产一区二区三区| 中文字幕中文字幕 亚洲国产| av俺也去在线播放| jiujiure精品视频在线| 黑人变态深video特大巨大| 4个黑人操素人视频网站精品91| 99久久激情婷婷综合五月天| 亚洲欧美一区二区三区爱爱动图| 偷拍自拍亚洲美腿丝袜| 综合精品久久久久97| 午夜场射精嗯嗯啊啊视频| 国产精品福利小视频a| 天天干天天操天天玩天天射 | 青青青爽视频在线播放| 日本女大学生的黄色小视频| 亚洲欧美激情国产综合久久久| 精品欧美一区二区vr在线观看| 2020国产在线不卡视频 | 在线免费观看黄页视频| 国产欧美日韩在线观看不卡| 最新国产精品网址在线观看| 亚洲成人激情av在线| 天天艹天天干天天操| 天天日夜夜操天天摸| 久久综合老鸭窝色综合久久| 性感美女福利视频网站| 欧美女同性恋免费a| 日韩成人性色生活片| 中文字幕人妻三级在线观看 | 特级欧美插插插插插bbbbb| 在线视频这里只有精品自拍| 国产高清97在线观看视频| 91极品大一女神正在播放| 亚洲图片欧美校园春色| 91极品新人『兔兔』精品新作| 国产精品久久综合久久| 久久丁香婷婷六月天| 91免费观看国产免费| 亚洲区美熟妇久久久久| sspd152中文字幕在线| 蜜桃精品久久久一区二区| 在线观看的a站 最新| 搡老熟女一区二区在线观看| 亚洲中文精品人人免费| 欧美日韩激情啪啪啪| 亚洲图片偷拍自拍区| 中文字幕之无码色多多| 亚洲精品无码久久久久不卡| 国产精品入口麻豆啊啊啊| 肏插流水妹子在线乐播下载| jiujiure精品视频在线| 久久久91蜜桃精品ad| 2018最新中文字幕在线观看| 日本一本午夜在线播放| 我想看操逼黄色大片| 精内国产乱码久久久久久| 亚洲中文字幕综合小综合| 色综合色综合色综合色| 青青操免费日综合视频观看| 9l人妻人人爽人人爽| av无限看熟女人妻另类av| 一个色综合男人天堂| 国产片免费观看在线观看| 日本熟妇丰满厨房55| 97国产精品97久久| 日韩av中文在线免费观看| 黄色中文字幕在线播放| 亚洲粉嫩av一区二区三区| 国产精品午夜国产小视频| 天天操天天操天天碰| 精品少妇一二三视频在线| 色综合色综合色综合色| 国产在线观看黄色视频| 55夜色66夜色国产精品站| 少妇深喉口爆吞精韩国| 欧美在线一二三视频| 中文字幕亚洲中文字幕| 操的小逼流水的文章| 成人亚洲精品国产精品| 国产成人一区二区三区电影网站| 宅男噜噜噜666国产| 馒头大胆亚洲一区二区| 美女av色播在线播放| av日韩在线观看大全| 都市家庭人妻激情自拍视频| 欧美中文字幕一区最新网址| 亚洲欧美综合另类13p| 日本乱人一区二区三区| 视频一区二区综合精品| 国产高清97在线观看视频| 男人天堂最新地址av| heyzo蜜桃熟女人妻| 人妻爱爱 中文字幕| 污污小视频91在线观看| 亚洲1卡2卡三卡4卡在线观看| 免费av岛国天堂网站| 亚洲欧美国产综合777| 日本女大学生的黄色小视频| 不卡一不卡二不卡三| 欧美激情精品在线观看| 国产片免费观看在线观看| 男大肉棒猛烈插女免费视频 | 成年人黄色片免费网站| 亚洲精品乱码久久久本| 免费观看理论片完整版| 91亚洲手机在线视频播放| 老鸭窝在线观看一区| 人人妻人人澡人人爽人人dvl| 亚洲成人线上免费视频观看| 馒头大胆亚洲一区二区| 亚洲中文字幕乱码区| 黄色三级网站免费下载| free性日本少妇| 成年人黄色片免费网站| 国内资源最丰富的网站| 黄色视频成年人免费观看| 91免费观看在线网站 | 777奇米久久精品一区| 天天干天天操天天扣| 天天干天天操天天摸天天射| 特一级特级黄色网片| www骚国产精品视频| 亚洲美女美妇久久字幕组| 亚洲综合自拍视频一区| 中文字幕高清资源站| 日韩亚洲高清在线观看| 最近中文2019年在线看| 免费在线观看污污视频网站| 日本韩国在线观看一区二区| 在线观看免费岛国av| 色婷婷综合激情五月免费观看| 国产亚州色婷婷久久99精品| 中文字幕人妻被公上司喝醉在线| 沈阳熟妇28厘米大战黑人| 人妻少妇性色欲欧美日韩| 日韩精品二区一区久久| 边摸边做超爽毛片18禁色戒 | 韩国AV无码不卡在线播放| 被大鸡吧操的好舒服视频免费| 国产剧情演绎系列丝袜高跟| 亚洲卡1卡2卡三卡四老狼| 精彩视频99免费在线| 一区二区三区久久久91| 国产综合高清在线观看| 亚洲少妇高潮免费观看| 日本最新一二三区不卡在线| 80电影天堂网官网| 午夜频道成人在线91| 888欧美视频在线| 欧美黄色录像免费看的| 中文字幕在线第一页成人| 亚洲公开视频在线观看| 19一区二区三区在线播放| 91天堂精品一区二区| 888欧美视频在线| 亚洲国产免费av一区二区三区| 91久久国产成人免费网站| 福利视频广场一区二区| 97超碰国语国产97超碰| 欧美精品亚洲精品日韩在线| 男人和女人激情视频| 超鹏97历史在线观看| 亚洲图库另类图片区| 成年美女黄网站18禁久久| 天堂中文字幕翔田av| 中文字幕在线观看国产片| 亚洲精品国产在线电影| 一个人免费在线观看ww视频| 蜜桃专区一区二区在线观看| 91精品激情五月婷婷在线| 成人亚洲国产综合精品| 欧美80老妇人性视频| 91国内精品自线在拍白富美| 高清成人av一区三区| 天天射,天天操,天天说| 亚洲图库另类图片区| 东京干手机福利视频| 91精品免费久久久久久| 精品久久久久久久久久久久人妻| 国产综合精品久久久久蜜臀| 国产精品视频欧美一区二区| 亚洲一区二区三区偷拍女厕91| 99婷婷在线观看视频| 亚洲熟女久久久36d| 视频一区二区综合精品| 女同久久精品秋霞网| 伊人情人综合成人久久网小说| 日韩欧美在线观看不卡一区二区| 在线国产中文字幕视频| 欧美特级特黄a大片免费| av老司机精品在线观看| 日本高清撒尿pissing| 高潮视频在线快速观看国家快速| 99国内精品永久免费视频| 淫秽激情视频免费观看| 日本高清在线不卡一区二区| 亚洲最大黄了色网站| 国产福利在线视频一区| aaa久久久久久久久| 青娱乐蜜桃臀av色| 3344免费偷拍视频| gay gay男男瑟瑟在线网站| 国产免费高清视频视频| 岛国毛片视频免费在线观看| 天天躁夜夜躁日日躁a麻豆| 91欧美在线免费观看| 中文字幕av男人天堂| 少妇高潮无套内谢麻豆| 91超碰青青中文字幕| 亚洲av日韩高清hd| 欧美精品久久久久久影院| 天天操天天射天天操天天天| 搞黄色在线免费观看| 日本一区精品视频在线观看| 亚洲激情,偷拍视频| 久草福利电影在线观看| 亚洲精品麻豆免费在线观看| 免费观看成年人视频在线观看| 亚洲最大免费在线观看| 无忧传媒在线观看视频| 亚洲少妇高潮免费观看| 亚洲免费国产在线日韩| 色狠狠av线不卡香蕉一区二区| 色花堂在线av中文字幕九九| 天天操天天干天天日狠狠插| 亚洲 色图 偷拍 欧美| 国产精品成久久久久三级蜜臀av| 超pen在线观看视频公开97| 班长撕开乳罩揉我胸好爽| 天天操,天天干,天天射| 天天做天天爽夜夜做少妇| 国产午夜激情福利小视频在线| 国产麻豆91在线视频| 经典av尤物一区二区| 亚洲一区av中文字幕在线观看| 韩国爱爱视频中文字幕| 久草电影免费在线观看| 美女张开腿让男生操在线看| 精品人妻一二三区久久| 亚洲国产第一页在线观看| 午夜在线观看一区视频| 亚洲女人的天堂av| 51精品视频免费在线观看| 我想看操逼黄色大片| 久久免费看少妇高潮完整版| 午夜精品福利91av| 和邻居少妇愉情中文字幕| 夜女神免费福利视频| 高潮视频在线快速观看国家快速| 亚洲欧美一区二区三区电影| 亚洲一区二区三区五区 | 香蕉91一区二区三区| 亚欧在线视频你懂的| 国产精选一区在线播放| 精品视频一区二区三区四区五区| 久草视频中文字幕在线观看| 黄色视频成年人免费观看| 欧美在线偷拍视频免费看| 欧美色呦呦最新网址| 大陆av手机在线观看| 亚洲欧美色一区二区| 五十路熟女人妻一区二| 午夜频道成人在线91| 77久久久久国产精产品| 天天日天天添天天爽| caoporm超碰国产| 啊慢点鸡巴太大了啊舒服视频| 天天日天天干天天爱| 亚洲第一伊人天堂网| 日韩成人性色生活片| xxx日本hd高清| 成人乱码一区二区三区av| 精品亚洲在线免费观看| aⅴ五十路av熟女中出| 777奇米久久精品一区| 大鸡吧插逼逼视频免费看| 女生自摸在线观看一区二区三区| 一区二区三区综合视频| 男生舔女生逼逼视频| 人妻丝袜榨强中文字幕| 欧美视频综合第一页| www日韩毛片av| 自拍偷拍 国产资源| 中文字幕免费福利视频6| av在线免费资源站| 区一区二区三国产中文字幕| 桃色视频在线观看一区二区| 自拍偷区二区三区麻豆| 免费手机黄页网址大全| 一二三中文乱码亚洲乱码one| 中国无遮挡白丝袜二区精品| 国产日本欧美亚洲精品视| 人人爱人人妻人人澡39| 中文字幕熟女人妻久久久| 美洲精品一二三产区区别| 欧美国品一二三产区区别| 4个黑人操素人视频网站精品91| 一区二区三区久久久91| 人妻少妇精品久久久久久| 国产黄色片蝌蚪九色91| h国产小视频福利在线观看| av在线免费资源站| 美女操逼免费短视频下载链接| 欧美日韩一区二区电影在线观看| 婷婷久久一区二区字幕网址你懂得 | 懂色av蜜桃a v| 丝袜肉丝一区二区三区四区在线| 91欧美在线免费观看| 2025年人妻中文字幕乱码在线| 国产福利小视频二区| 中文字幕在线观看国产片| 亚洲欧美国产麻豆综合| 黄色视频在线观看高清无码| gogo国模私拍视频| 乱亲女秽乱长久久久| 亚洲欧美综合另类13p| 大香蕉福利在线观看| 天堂av在线最新版在线| 乱亲女秽乱长久久久| 视频二区在线视频观看| 懂色av蜜桃a v| chinese国产盗摄一区二区| 日韩一个色综合导航| 99精品亚洲av无码国产另类| 揄拍成人国产精品免费看视频| 91天堂精品一区二区| 日本一二三区不卡无| 亚洲av色香蕉一区二区三区| 自拍 日韩 欧美激情| 不卡日韩av在线观看| 亚洲精品成人网久久久久久小说| 大鸡巴操娇小玲珑的女孩逼| 51国产成人精品视频| 78色精品一区二区三区| 欧美日韩中文字幕欧美| 一级黄色av在线观看| 免费观看污视频网站| 国产美女午夜福利久久| 日日摸夜夜添夜夜添毛片性色av| 成年人的在线免费视频| 极品粉嫩小泬白浆20p主播| 91av精品视频在线| 亚洲中文字幕乱码区| 中文字幕在线一区精品| 综合一区二区三区蜜臀| 亚洲特黄aaaa片| 男人操女人的逼免费视频| 少妇人妻久久久久视频黄片| 青青伊人一精品视频| 少妇被强干到高潮视频在线观看| av在线观看网址av| 亚洲一区二区久久久人妻| 亚洲福利午夜久久久精品电影网 | 亚洲av午夜免费观看| 伊人精品福利综合导航| 国产精品黄色的av| 人妻熟女中文字幕aⅴ在线| 美女操逼免费短视频下载链接| 亚洲美女高潮喷浆视频| 国产又粗又猛又爽又黄的视频美国| 国产精品成久久久久三级蜜臀av| 在线观看欧美黄片一区二区三区| 中文字幕一区二区人妻电影冢本| 亚洲午夜福利中文乱码字幕| 宅男噜噜噜666免费观看| 国产精品免费不卡av| 性色蜜臀av一区二区三区| 亚洲麻豆一区二区三区| 77久久久久国产精产品| 好太好爽好想要免费| 亚洲av极品精品在线观看| 91精品激情五月婷婷在线| 亚洲av天堂在线播放| 硬鸡巴动态操女人逼视频| 久久人人做人人妻人人玩精品vr| 欧美成人精品在线观看| 欧美精品欧美极品欧美视频| 国产精品国产三级国产午| 人妻久久久精品69系列| 色综合久久久久久久久中文| 三上悠亚和黑人665番号| 亚洲va国产va欧美va在线| 亚洲精品国产在线电影| 亚洲av自拍天堂网| 精品人妻一二三区久久| 熟女人妻一区二区精品视频| 亚洲另类综合一区小说| 国产使劲操在线播放| 国产精彩福利精品视频| av天堂中文免费在线| 中文字幕在线免费第一页| 亚洲老熟妇日本老妇| 天天操天天干天天日狠狠插| 18禁污污污app下载| 国产亚洲精品视频合集| 男人和女人激情视频| 春色激情网欧美成人| 日韩北条麻妃一区在线| 亚洲熟女女同志女同| 一区二区视频视频视频| 日本女人一级免费片| aⅴ精产国品一二三产品| 国产日韩精品免费在线| 激情国产小视频在线| 欧美特色aaa大片| 99国内小视频在现欢看| 久久久久久久亚洲午夜综合福利 | 成人亚洲国产综合精品| 中文字幕在线永久免费播放| 亚洲精品一区二区三区老狼| 亚洲中文精品人人免费| 我想看操逼黄色大片| 老鸭窝日韩精品视频观看| 夏目彩春在线中文字幕| www天堂在线久久| 欧美在线一二三视频| 精品区一区二区三区四区人妻| 91精品免费久久久久久| 一区二区三区日本伦理| 人人妻人人澡人人爽人人dvl| 丝袜肉丝一区二区三区四区在线| 中文字幕日韩人妻在线三区| 狠狠的往里顶撞h百合| 天码人妻一区二区三区在线看| aⅴ精产国品一二三产品| 中文字幕综合一区二区| 亚洲卡1卡2卡三卡四老狼| 好了av中文字幕在线| 91久久精品色伊人6882| 成熟熟女国产精品一区| 亚洲av无硬久久精品蜜桃| 一区二区三区的久久的蜜桃的视频 | 午夜毛片不卡免费观看视频 | 人妻丝袜诱惑我操她视频| 五十路av熟女松本翔子| 青青青青爽手机在线| 中文字幕高清资源站| 男人天堂av天天操| 亚洲国产精品美女在线观看| 欧美日韩熟女一区二区三区| 夜色福利视频在线观看| 成年人黄色片免费网站| 大香蕉大香蕉在线有码 av| 国产janese在线播放| 1区2区3区不卡视频| 97年大学生大白天操逼| 日本免费一级黄色录像| 青草亚洲视频在线观看| 精品区一区二区三区四区人妻| 亚洲国产美女一区二区三区软件 | 天天日天天干天天干天天日| 一区国内二区日韩三区欧美| 五月激情婷婷久久综合网| 天天干天天啪天天舔| 成人av电影免费版| 直接观看免费黄网站| 99精品国产aⅴ在线观看| 亚洲激情偷拍一区二区| 国产精品精品精品999| 中文字日产幕乱六区蜜桃| 视频 国产 精品 熟女 | 青青草人人妻人人妻| 综合色区亚洲熟妇shxstz| 国产一级麻豆精品免费| 国产97视频在线精品| 自拍偷拍亚洲精品第2页| 国产精彩福利精品视频| 国产精彩对白一区二区三区| 国产又大又黄免费观看| 欧美色呦呦最新网址| 涩爱综合久久五月蜜臀| 十八禁在线观看地址免费| 老师让我插进去69AV| 春色激情网欧美成人| 亚洲特黄aaaa片| 天堂中文字幕翔田av| 青青擦在线视频国产在线| 日韩av免费观看一区| 中文字幕 码 在线视频| 性感美女高潮视频久久久| 91老熟女连续高潮对白| www久久久久久久久久久| 丝袜美腿视频诱惑亚洲无| 久久久噜噜噜久久熟女av| 天堂av在线最新版在线| 天天想要天天操天天干| 18禁污污污app下载| 国产janese在线播放| 国产精品久久久黄网站| 91老师蜜桃臀大屁股| 超级碰碰在线视频免费观看| 亚洲另类综合一区小说| 一个人免费在线观看ww视频 | 国产日韩精品免费在线| 夜色17s精品人妻熟女| 亚洲日本一区二区三区| 性感美女诱惑福利视频| 888亚洲欧美国产va在线播放| 少妇深喉口爆吞精韩国| 一区二区三区视频,福利一区二区 丰满的子国产在线观看 | 97欧洲一区二区精品免费| 一区国内二区日韩三区欧美| 亚洲第一伊人天堂网| 国产高清精品一区二区三区| 欧美亚洲一二三区蜜臀| 一区二区麻豆传媒黄片| 小穴多水久久精品免费看| 国产精品久久久久久久女人18| 国产av一区2区3区| 成年人免费看在线视频| 午夜极品美女福利视频| 超黄超污网站在线观看| 亚洲午夜电影在线观看| 亚洲中文字幕校园春色| 亚洲图片偷拍自拍区| 亚洲精品 日韩电影| 色97视频在线播放| 男生舔女生逼逼的视频| 久久久久久久一区二区三| 少妇ww搡性bbb91| 亚洲国产美女一区二区三区软件 | 亚洲中文字幕国产日韩| 日本成人不卡一区二区| 97超碰人人搞人人| 亚洲综合在线观看免费| 精品久久久久久久久久久久人妻| 日韩av免费观看一区| 中文字幕乱码人妻电影| 天天干天天操天天爽天天摸| 亚洲欧美在线视频第一页| 91国偷自产一区二区三区精品| 亚洲成人黄色一区二区三区| 黄页网视频在线免费观看| 黄色男人的天堂视频| 午夜美女少妇福利视频| 亚洲一区久久免费视频| 成人30分钟免费视频| 一区二区三区激情在线| 强行扒开双腿猛烈进入免费版| 小穴多水久久精品免费看| 成人sm视频在线观看| 91香蕉成人app下载| 熟女妇女老妇一二三区| 99热久久这里只有精品| 国产福利在线视频一区| 偷拍自拍福利视频在线观看| 婷婷色国产黑丝少妇勾搭AV| 曰本无码人妻丰满熟妇啪啪| wwwxxx一级黄色片| 精品黑人巨大在线一区| www久久久久久久久久久| 激情人妻校园春色亚洲欧美 | 免费黄高清无码国产| 亚洲人妻视频在线网| 欧洲黄页网免费观看| 91久久国产成人免费网站| 精品人妻每日一部精品| 亚洲av第国产精品| 岛国av高清在线成人在线| 中文字幕人妻三级在线观看| 极品性荡少妇一区二区色欲| 韩国AV无码不卡在线播放| 免费看国产又粗又猛又爽又黄视频 | 3344免费偷拍视频| 国产精品三级三级三级| 粉嫩小穴流水视频在线观看| 清纯美女在线观看国产| 人妻丰满熟妇综合网| 国产精品自拍视频大全| aaa久久久久久久久| 久草视频在线免播放| 国产欧美日韩第三页| 亚洲免费国产在线日韩| av中文在线天堂精品| 好了av中文字幕在线| 无码中文字幕波多野不卡| 亚洲人一区二区中文字幕| 日本少妇在线视频大香蕉在线观看 | 大香蕉玖玖一区2区| 国产女人被做到高潮免费视频| 日本少妇高清视频xxxxx| 午夜在线一区二区免费| 青青青青视频在线播放| 80电影天堂网官网| 亚洲国产精品久久久久蜜桃| 天天日天天透天天操| 国产三级片久久久久久久| 不卡一区一区三区在线| 欧美 亚洲 另类综合| 亚洲的电影一区二区三区| 成年女人免费播放视频| 成人乱码一区二区三区av| 美女福利视频导航网站| 在线观看国产网站资源| 特大黑人巨大xxxx| 午夜在线精品偷拍一区二| 中文字幕日韩91人妻在线| 精品日产卡一卡二卡国色天香| 天堂v男人视频在线观看| 黄色无码鸡吧操逼视频| 91‖亚洲‖国产熟女| 国产chinesehd精品麻豆| 成人性黑人一级av| 93精品视频在线观看| 91www一区二区三区| 成人亚洲国产综合精品| 欧美在线一二三视频| 亚洲av黄色在线网站| 欧美性感尤物人妻在线免费看| 午夜在线精品偷拍一区二| 欧美交性又色又爽又黄麻豆| 91免费福利网91麻豆国产精品| 综合国产成人在线观看| 香港一级特黄大片在线播放| 91试看福利一分钟| 中文字幕中文字幕人妻| 黄色中文字幕在线播放| 久久久久久久一区二区三| 人妻少妇一区二区三区蜜桃| 亚洲另类图片蜜臀av| 午夜激情高清在线观看| 夜夜嗨av一区二区三区中文字幕| 国产麻豆剧传媒精品国产av蜜桃| 人妻少妇中文有码精品| 亚洲欧美一区二区三区爱爱动图| 精品高潮呻吟久久av| 男人插女人视频网站| 粗大的内捧猛烈进出爽大牛汉子| 日韩黄色片在线观看网站| 亚洲美女美妇久久字幕组| 91欧美在线免费观看| 一区二区视频在线观看免费观看| 日韩近亲视频在线观看| 黑人进入丰满少妇视频| 国产高清精品一区二区三区| caoporm超碰国产| 美洲精品一二三产区区别| 40道精品招牌菜特色| 综合一区二区三区蜜臀| 日比视频老公慢点好舒服啊| av在线免费观看亚洲天堂| 夜女神免费福利视频| 巨乳人妻日下部加奈被邻居中出| 国产亚洲国产av网站在线| 超污视频在线观看污污污| 啪啪啪啪啪啪啪啪啪啪黄色| 色偷偷伊人大杳蕉综合网| 91精品国产91青青碰| 免费岛国喷水视频在线观看| 青青青青青免费视频| 人妻av无码专区久久绿巨人| 午夜精品九一唐人麻豆嫩草成人| 亚洲偷自拍高清视频| 亚洲天堂第一页中文字幕| 黄色片黄色片wyaa| 中文字幕日韩人妻在线三区| 天天日天天爽天天爽| 亚洲图库另类图片区| 可以在线观看的av中文字幕| 2022中文字幕在线| 91精品国产91青青碰| 一区二区三区毛片国产一区| 日韩剧情片电影在线收看| 天天插天天狠天天操| 老鸭窝日韩精品视频观看| 亚洲欧美国产麻豆综合| 爱有来生高清在线中文字幕| 99精品久久久久久久91蜜桃| 93视频一区二区三区| 男大肉棒猛烈插女免费视频 | 久草视频首页在线观看| 男生舔女生逼逼的视频| 大香蕉日本伊人中文在线| 噜噜色噜噜噜久色超碰| 日本美女性生活一级片| 手机看片福利盒子日韩在线播放| 五十路丰满人妻熟妇| 欧美精品国产综合久久| 无码中文字幕波多野不卡| 人妻少妇性色欲欧美日韩| 黄色录像鸡巴插进去| 亚洲一区av中文字幕在线观看| 一区二区三区 自拍偷拍| 精品国产成人亚洲午夜| 2o22av在线视频| 亚洲1区2区3区精华液| 特大黑人巨大xxxx| 最新国产亚洲精品中文在线| 亚洲综合色在线免费观看| 午夜国产福利在线观看| 红桃av成人在线观看| 在线免费观看黄页视频| 色哟哟在线网站入口| 成年人免费看在线视频| 亚洲午夜电影之麻豆 | 欧美中文字幕一区最新网址| 日韩三级黄色片网站| 国产精品自拍偷拍a| 搞黄色在线免费观看| 精品首页在线观看视频| 自拍偷拍,中文字幕| 欧美视频一区免费在线| 国产黑丝高跟鞋视频在线播放| 天天干天天插天天谢| 黄色片一级美女黄色片| 国产亚洲精品视频合集| 夜女神免费福利视频| 姐姐的朋友2在线观看中文字幕| 亚洲护士一区二区三区| 国产一区二区三免费视频| 国产精品亚洲а∨天堂免| 国产成人午夜精品福利| 成人福利视频免费在线| 欧美3p在线观看一区二区三区| 久青青草视频手机在线免费观看| 国产乱弄免费视频观看| 精品一区二区亚洲欧美| av老司机精品在线观看| 日本少妇精品免费视频| 丁香花免费在线观看中文字幕| 日本精品美女在线观看| 免费在线黄色观看网站| 亚洲图片偷拍自拍区| 亚洲精品 日韩电影| 边摸边做超爽毛片18禁色戒| 不卡精品视频在线观看| 欧美黄片精彩在线免费观看| 免费啪啪啪在线观看视频| 日韩精品激情在线观看| 老司机午夜精品视频资源| 大陆精品一区二区三区久久| 欧美精品一二三视频| 中文字幕1卡1区2区3区| 亚洲欧美综合在线探花| 天天干天天日天天干天天操| 99re6热在线精品| gay gay男男瑟瑟在线网站| 最新欧美一二三视频| 久草极品美女视频在线观看| 11久久久久久久久久久| v888av在线观看视频| 大鸡吧插逼逼视频免费看| 国产精品一二三不卡带免费视频 | 2021最新热播中文字幕| 日韩人妻丝袜中文字幕| 天干天天天色天天日天天射| 男人天堂av天天操| 97超碰免费在线视频| 亚洲免费在线视频网站| 亚洲伊人久久精品影院一美女洗澡| 不卡日韩av在线观看| 国产精品伦理片一区二区| 国产乱子伦一二三区| 91精品国产观看免费| 国产精品黄页网站视频| 动漫美女的小穴视频| 日韩熟女系列一区二区三区| 老司机午夜精品视频资源| 成人乱码一区二区三区av| 精品一线二线三线日本| 粉嫩欧美美人妻小视频| wwwxxx一级黄色片| 人妻久久无码中文成人| 亚洲av琪琪男人的天堂| 干逼又爽又黄又免费的视频| 偷拍自拍亚洲视频在线观看| 欧美黄色录像免费看的| 动漫美女的小穴视频| 91成人精品亚洲国产| 欧美天堂av无线av欧美| 91 亚洲视频在线观看| 97青青青手机在线视频| 最新日韩av传媒在线| 日韩国产乱码中文字幕| nagger可以指黑人吗| av中文字幕网址在线| 1区2区3区不卡视频| 精品国产污污免费网站入口自 | 自拍偷拍亚洲欧美在线视频| 国产在线免费观看成人| 直接观看免费黄网站| 啪啪啪啪啪啪啪啪啪啪黄色| 青青青青青青青青青青草青青| 欧美黑人性猛交xxxxⅹooo| 国产午夜男女爽爽爽爽爽视频| 淫秽激情视频免费观看| 人妻自拍视频中国大陆| 粗大的内捧猛烈进出爽大牛汉子| av一本二本在线观看| 亚洲成人精品女人久久久| 国产精品视频资源在线播放| 亚洲熟女女同志女同| 在线免费观看黄页视频| 日韩伦理短片在线观看| 亚洲欧洲一区二区在线观看| 国产 在线 免费 精品| 天天干天天操天天爽天天摸 | 亚洲欧美久久久久久久久| 99视频精品全部15| 亚洲综合一区成人在线| 日本黄在免费看视频| 97资源人妻免费在线视频| 欧美精品资源在线观看| 国产高清97在线观看视频| 五月色婷婷综合开心网4438| 色天天天天射天天舔| 一级a看免费观看网站| 红桃av成人在线观看| 欧美日韩国产一区二区三区三州| 久久综合老鸭窝色综合久久| 国产一区二区火爆视频| 91福利视频免费在线观看| 中文字幕一区二 区二三区四区| 少妇人妻二三区视频| 国产精品一区二区av国| 在线视频自拍第三页| 蜜臀成人av在线播放| 少妇高潮无套内谢麻豆| 春色激情网欧美成人| 无码日韩人妻精品久久| 最新日韩av传媒在线| 无忧传媒在线观看视频| 国产福利小视频免费观看| 欧美专区日韩专区国产专区| 日韩av大胆在线观看| 玖玖一区二区在线观看| 人人爽亚洲av人人爽av| 成人国产激情自拍三区| 狠狠嗨日韩综合久久| 桃色视频在线观看一区二区| 精品高跟鞋丝袜一区二区| 日日夜夜狠狠干视频| 欧美天堂av无线av欧美| 午夜美女福利小视频| 亚洲 中文字幕在线 日韩| 一区二区久久成人网| 天天操天天干天天艹| 天天艹天天干天天操| 天天日天天干天天舔天天射| 青青草成人福利电影| 宅男噜噜噜666免费观看| 国产黄色片在线收看| 熟女妇女老妇一二三区| 日本熟妇一区二区x x| 久久三久久三久久三久久| 最新91九色国产在线观看| 亚洲成人精品女人久久久| 人人妻人人人操人人人爽| 精品高潮呻吟久久av| 亚洲中文字字幕乱码| 亚洲成人三级在线播放 | 国产麻豆剧传媒精品国产av蜜桃| 天天干天天操天天插天天日| 极品性荡少妇一区二区色欲| 午夜久久香蕉电影网| 亚洲人妻视频在线网| 亚洲一区自拍高清免费视频| 精品国产成人亚洲午夜| 天天干天天插天天谢| 99一区二区在线观看| 亚洲av无硬久久精品蜜桃| 99国产精品窥熟女精品| 超碰97人人澡人人| 中文字幕中文字幕人妻| 国产成人精品午夜福利训2021| 老司机你懂得福利视频| 黄片三级三级三级在线观看| 蜜桃视频17c在线一区二区| 久久午夜夜伦痒痒想咳嗽P| 亚洲图片偷拍自拍区| 亚国产成人精品久久久| 国产av自拍偷拍盛宴| 亚洲精品国产综合久久久久久久久| 老司机在线精品福利视频| 青青草原色片网站在线观看| 美女小视频网站在线| 精品区一区二区三区四区人妻| 97超碰国语国产97超碰| 亚洲av在线观看尤物| 亚洲蜜臀av一区二区三区九色| 天干天天天色天天日天天射| 亚洲偷自拍高清视频| 国产卡一卡二卡三乱码手机| 免费男阳茎伸入女阳道视频| 38av一区二区三区| 韩国一级特黄大片做受| 久精品人妻一区二区三区| 日韩无码国产精品强奸乱伦| 日本最新一二三区不卡在线| 亚洲国际青青操综合网站| 天天日天天干天天干天天日| 天天干天天搞天天摸| 亚洲卡1卡2卡三卡四老狼| 非洲黑人一级特黄片| 久久久久久性虐视频| 天天操夜夜骑日日摸| 欧美日本在线观看一区二区| 在线成人日韩av电影| 动漫精品视频在线观看| 亚洲国产欧美国产综合在线| 国产黄色片在线收看| 91桃色成人网络在线观看| 宅男噜噜噜666国产| 中国熟女一区二区性xx| 欧美精品 日韩国产| www日韩毛片av| 都市家庭人妻激情自拍视频| 亚洲av色香蕉一区二区三区| 欧美va不卡视频在线观看 | 2022中文字幕在线| 男人的天堂在线黄色| 久久久久91精品推荐99| 熟女91pooyn熟女| 91九色国产熟女一区二区| 中国黄片视频一区91| 2022天天干天天操| 亚洲第一黄色在线观看| 蝴蝶伊人久久中文娱乐网| 一级a看免费观看网站| 九色精品视频在线播放| 天天插天天狠天天操| 国产精品手机在线看片| 午夜免费体验区在线观看| 欧美日韩情色在线观看| 一区二区三区激情在线| 亚洲国产精品中文字幕网站| 9色在线视频免费观看| 欧美日韩亚洲国产无线码| 岛国一区二区三区视频在线| av在线免费中文字幕| 91试看福利一分钟| 在线制服丝袜中文字幕| 1区2区3区不卡视频| 国产精品自偷自拍啪啪啪| 专门看国产熟妇的网站| japanese五十路熟女熟妇| 瑟瑟视频在线观看免费视频| 中文字幕之无码色多多| 青青在线视频性感少妇和隔壁黑丝| 欧美黑人性暴力猛交喷水| 在线观看一区二区三级| 97超碰国语国产97超碰| 亚洲精品乱码久久久本| 日韩中文字幕在线播放第二页| av网站色偷偷婷婷网男人的天堂| 天天操夜夜操天天操天天操 | 五十路熟女人妻一区二| 99av国产精品欲麻豆| 国产高清女主播在线| 在线免费观看日本片| 天天日天天天天天天天天天天| 97青青青手机在线视频| 宅男噜噜噜666免费观看| 80电影天堂网官网| 青青社区2国产视频| 绝色少妇高潮3在线观看| 好吊视频—区二区三区| 经典亚洲伊人第一页| 欲乱人妻少妇在线视频裸| 日本欧美视频在线观看三区| 亚洲av香蕉一区区二区三区犇| 亚洲熟妇久久无码精品| 国产精品国产三级麻豆| av视网站在线观看| 亚洲欧美国产综合777| 天天插天天色天天日| 伊人网中文字幕在线视频| 最新国产精品网址在线观看| 搡老熟女一区二区在线观看| 老师让我插进去69AV| 久久丁香花五月天色婷婷| 99精品视频在线观看婷婷| 免费看高清av的网站| 国产精选一区在线播放| 日本男女操逼视频免费看| 最新中文字幕免费视频| 欧美另类一区二区视频| 免费成人av中文字幕| 一区二区视频在线观看视频在线| 婷婷久久一区二区字幕网址你懂得| 日韩写真福利视频在线观看| 天天日天天干天天要| 毛茸茸的大外阴中国视频| 夜色17s精品人妻熟女| 宅男噜噜噜666国产| 18禁污污污app下载| 国产视频在线视频播放| 国产亚洲欧美视频网站| 亚洲综合在线观看免费| 欧美偷拍亚洲一区二区| 直接观看免费黄网站| 欧美性感尤物人妻在线免费看| 男生舔女生逼逼的视频| 亚洲午夜电影之麻豆| 91在线视频在线精品3| 40道精品招牌菜特色| 国产真实乱子伦a视频 | 亚洲高清免费在线观看视频| 超级碰碰在线视频免费观看| 欧美aa一级一区三区四区| 2021久久免费视频| 日韩影片一区二区三区不卡免费| 欧美成人综合色在线噜噜| 亚洲国产最大av综合| 一个色综合男人天堂| 久久精品国产亚洲精品166m| 青青青青青操视频在线观看| 99国内小视频在现欢看| 2022国产精品视频| 亚洲综合自拍视频一区| 夜色撩人久久7777| 成人精品视频99第一页| 三上悠亚和黑人665番号| 亚洲伊人色一综合网| v888av在线观看视频| 亚洲中文字幕校园春色| 亚洲欧美清纯唯美另类| 天天躁夜夜躁日日躁a麻豆| 日韩少妇人妻精品无码专区| 视频一区二区在线免费播放| 三级等保密码要求条款| 成年人黄视频在线观看| 久久久久久久精品老熟妇| 欧美第一页在线免费观看视频| 国产精品人妻一区二区三区网站| 十八禁在线观看地址免费| 日日夜夜精品一二三| 欧美精品黑人性xxxx| 在线观看成人国产电影| 美女张开两腿让男人桶av| 亚洲专区激情在线观看视频| 三级等保密码要求条款| 偷拍美女一区二区三区| 亚洲av男人天堂久久| free性日本少妇| 75国产综合在线视频| 亚洲熟妇x久久av久久| 欧美精品伦理三区四区 | 色狠狠av线不卡香蕉一区二区 | 不戴胸罩引我诱的隔壁的人妻| 欧美女同性恋免费a| 亚洲变态另类色图天堂网| 最后99天全集在线观看| 2020国产在线不卡视频| 亚洲日本一区二区三区| 国产亚洲精品欧洲在线观看| 自拍偷拍一区二区三区图片| 少妇与子乱在线观看| 国产va在线观看精品| 啪啪啪18禁一区二区三区| 国产janese在线播放| 五月天久久激情视频| 婷婷综合亚洲爱久久| 在线免费观看视频一二区| 91社福利《在线观看| 亚洲国产欧美一区二区三区久久| 亚洲午夜伦理视频在线| 国产视频在线视频播放| 亚洲一区制服丝袜美腿| 精品人妻一二三区久久| 日本免费午夜视频网站| 精品区一区二区三区四区人妻| 欧美日韩亚洲国产无线码| 成人区人妻精品一区二视频| 黄色片年轻人在线观看| 天天操夜夜骑日日摸| 天天爽夜夜爽人人爽QC| 91麻豆精品久久久久| 精品av国产一区二区三区四区| 男大肉棒猛烈插女免费视频| 五十路熟女av天堂| 97国产福利小视频合集| 亚洲1区2区3区精华液| 久久久久久cao我的性感人妻| 班长撕开乳罩揉我胸好爽| 97成人免费在线观看网站| 色综合天天综合网国产成人| 精品成人午夜免费看| 91高清成人在线视频| 大胸性感美女羞爽操逼毛片| 日本精品一区二区三区在线视频。 | 一区二区视频在线观看免费观看| 麻豆性色视频在线观看| 999久久久久999| 欧美偷拍亚洲一区二区| 在线播放国产黄色av| 青青草亚洲国产精品视频| 国产精品国产三级国产午| 中文字幕人妻三级在线观看| 亚洲男人让女人爽的视频| caoporm超碰国产| 亚洲av午夜免费观看| 亚洲一区二区激情在线| 久久这里只有精彩视频免费| 男人天堂av天天操| 在线视频国产欧美日韩| 青青尤物在线观看视频网站| 五十路熟女人妻一区二| av亚洲中文天堂字幕网| 中文字幕无码日韩专区免费| 欧美一区二区三区啪啪同性| 人妻丝袜诱惑我操她视频| 日日夜夜狠狠干视频| 日本在线一区二区不卡视频| 欧美黑人性暴力猛交喷水| 日本五十路熟新垣里子| 亚洲国产精品中文字幕网站| 视频 国产 精品 熟女 | 男人和女人激情视频| 国产激情av网站在线观看| 日韩精品电影亚洲一区| 欧美精品国产综合久久| 欧美成人黄片一区二区三区| 日韩精品中文字幕福利| 成人av免费不卡在线观看| 久久免看30视频口爆视频| 亚洲成人午夜电影在线观看| 性色av一区二区三区久久久| 91久久国产成人免费网站| 久久久久久cao我的性感人妻| 国产又大又黄免费观看| 亚洲中文字幕校园春色| 亚洲av午夜免费观看| 色av色婷婷人妻久久久精品高清| av大全在线播放免费| 男人的天堂av日韩亚洲| 久久精品久久精品亚洲人| 99精品免费观看视频| 护士特殊服务久久久久久久| sejizz在线视频| 韩国爱爱视频中文字幕| 午夜婷婷在线观看视频| 天天日天天日天天擦| 性色蜜臀av一区二区三区| 欧美80老妇人性视频| av成人在线观看一区| 国产亚洲成人免费在线观看| av日韩在线观看大全| 阿v天堂2014 一区亚洲| 亚洲av无码成人精品区辽| 亚洲自拍偷拍精品网| 天天爽夜夜爽人人爽QC| 女人精品内射国产99| 在线观看视频污一区| 大鸡巴操b视频在线| 亚洲蜜臀av一区二区三区九色| 亚洲图片偷拍自拍区| 亚洲免费福利一区二区三区| 亚洲人一区二区中文字幕| 人妻熟女中文字幕aⅴ在线| 亚洲成人黄色一区二区三区 | 99婷婷在线观看视频| 国产精品福利小视频a| 日本少妇人妻xxxxxhd| 93人妻人人揉人人澡人人| 一区二区三区四区五区性感视频| 涩爱综合久久五月蜜臀| 一区二区三区另类在线| 天天干天天操天天插天天日| 97少妇精品在线观看| 欧美精品欧美极品欧美视频| 91精品国产91久久自产久强| 中文字幕av男人天堂| 日本精品一区二区三区在线视频。 | 福利国产视频在线观看| 青青草精品在线视频观看| 国产极品精品免费视频| 色秀欧美视频第一页| 日韩欧美一级精品在线观看| 国产一级精品综合av| 日本av高清免费网站| 色呦呦视频在线观看视频| 亚洲区美熟妇久久久久| 久久亚洲天堂中文对白| 80电影天堂网官网| 日韩三级黄色片网站| 嫩草aⅴ一区二区三区| 久久精品国产999| 国产精品久久久久久久久福交 | 亚洲天堂精品久久久| 3344免费偷拍视频| 亚洲激情,偷拍视频| 天天日天天敢天天干| 日本黄在免费看视频| 欧美日韩高清午夜蜜桃大香蕉| 天天日天天添天天爽| 在线免费观看黄页视频| 十八禁在线观看地址免费| 中文字幕—97超碰网| 天天日天天透天天操| 国产美女精品福利在线| 极品丝袜一区二区三区| 久久久91蜜桃精品ad| 久久久久久97三级| 久久久久只精品国产三级| 午夜精品福利一区二区三区p| 国产精品一区二区三区蜜臀av| 一区二区三区日本伦理| 免费在线福利小视频| 天天色天天操天天舔| 日韩无码国产精品强奸乱伦| 国产精品一二三不卡带免费视频| 国产大学生援交正在播放| 国产成人无码精品久久久电影| 男人的天堂av日韩亚洲| 亚洲欧美另类自拍偷拍色图| 大鸡巴后入爆操大屁股美女| 国产va精品免费观看 | 亚洲综合一区成人在线| 欧美一区二区三区久久久aaa| 亚洲熟色妇av日韩熟色妇在线| 丝袜国产专区在线观看| 国产在线拍揄自揄视频网站| 大香蕉日本伊人中文在线| 激情国产小视频在线| 亚洲av日韩精品久久久| 不卡日韩av在线观看| 亚洲 欧美 精品 激情 偷拍| 精品视频国产在线观看| 亚洲午夜电影之麻豆| 大陆胖女人与丈夫操b国语高清 | 国产久久久精品毛片| 国产污污污污网站在线| 亚洲推理片免费看网站| 色婷婷综合激情五月免费观看| 亚洲 中文 自拍 无码| 丰满少妇人妻xxxxx| 久草福利电影在线观看| 2025年人妻中文字幕乱码在线| 欧美一区二区中文字幕电影 | 成人亚洲精品国产精品| 亚洲午夜电影在线观看| 亚洲一区制服丝袜美腿| 国产麻豆乱子伦午夜视频观看| 国产黄网站在线观看播放| 99久久99一区二区三区| 成人福利视频免费在线| 在线视频精品你懂的| 欧美久久一区二区伊人| 黄片大全在线观看观看| 91亚洲精品干熟女蜜桃频道 | 日日操综合成人av| 91she九色精品国产| 欧美aa一级一区三区四区| 国产在线拍揄自揄视频网站| 沙月文乃人妻侵犯中文字幕在线| 啪啪啪啪啪啪啪免费视频| 在线观看视频污一区| 91久久精品色伊人6882| 国产美女一区在线观看| caoporm超碰国产| 性欧美日本大妈母与子| 国产在线拍揄自揄视频网站| 日日夜夜精品一二三| 老司机福利精品免费视频一区二区| 亚洲av无码成人精品区辽| 国产av欧美精品高潮网站| 亚洲成人情色电影在线观看| 免费在线看的黄网站| wwwxxx一级黄色片| 一区二区在线视频中文字幕 | 色吉吉影音天天干天天操| 自拍偷拍日韩欧美一区二区| 国产黄色大片在线免费播放| 男人操女人逼逼视频网站| 5528327男人天堂| 天天干天天日天天谢综合156| 国产黑丝高跟鞋视频在线播放| 亚洲成人激情视频免费观看了| av视屏免费在线播放| 午夜的视频在线观看| 亚洲av香蕉一区区二区三区犇| 又大又湿又爽又紧A视频| 一区二区久久成人网| 午夜激情高清在线观看| 欧美第一页在线免费观看视频| 99人妻视频免费在线| 国产自拍黄片在线观看| av俺也去在线播放| 国产大学生援交正在播放| 中文字母永久播放1区2区3区| 在线免费观看日本伦理| 亚洲在线免费h观看网站| 亚洲一区二区三区av网站| 蜜臀av久久久久蜜臀av麻豆| 一区二区三区的久久的蜜桃的视频 | 自拍偷拍,中文字幕| 午夜国产免费福利av| 久久久久久久久久性潮| 亚洲最大免费在线观看| 老鸭窝日韩精品视频观看| 97欧洲一区二区精品免费| lutube在线成人免费看| 超碰公开大香蕉97| 热久久只有这里有精品| 91超碰青青中文字幕| 天天夜天天日天天日| 亚洲va欧美va人人爽3p| 国产高清精品极品美女| 五月色婷婷综合开心网4438| 亚洲国产精品免费在线观看| 国产精品成人xxxx| 绝顶痉挛大潮喷高潮无码| 2022国产精品视频| 五十路息与子猛烈交尾视频| 中文字幕奴隷色的舞台50| 日本一二三中文字幕| 五十路熟女av天堂| 国产高潮无码喷水AV片在线观看| huangse网站在线观看| 国产精品伦理片一区二区| 边摸边做超爽毛片18禁色戒 | 91精品综合久久久久3d动漫| 亚洲av天堂在线播放| 五十路老熟女码av| 国产精品3p和黑人大战| 国产一区自拍黄视频免费观看| 一二三中文乱码亚洲乱码one| 成人免费做爰高潮视频| 亚洲精品乱码久久久本| 大学生A级毛片免费视频| 国产又色又刺激在线视频 | 又粗又硬又猛又黄免费30| 精品国产污污免费网站入口自| 国产 在线 免费 精品| 99人妻视频免费在线| 99婷婷在线观看视频| 在线观看视频网站麻豆| 北条麻妃高跟丝袜啪啪| 含骚鸡巴玩逼逼视频| 久久尻中国美女视频| 亚洲国产成人av在线一区| 超碰97人人做人人爱| chinese国产盗摄一区二区| 欧美一区二区三区乱码在线播放 | 欧美视频不卡一区四区| 亚洲精品三级av在线免费观看| 在线国产中文字幕视频| 亚洲女人的天堂av| 中文字幕+中文字幕| 999九九久久久精品| 男生舔女生逼逼视频| nagger可以指黑人吗| 国产精品自拍在线视频| 国产性色生活片毛片春晓精品| 免费观看国产综合视频| a v欧美一区=区三区| 大鸡八强奸视频在线观看| 深田咏美亚洲一区二区| 狍和女人的王色毛片| 一区二区三区日韩久久| 干逼又爽又黄又免费的视频| 懂色av蜜桃a v| 成人性黑人一级av| 888欧美视频在线| 3337p日本欧洲大胆色噜噜| 热久久只有这里有精品| 国产精品久久综合久久| 超级碰碰在线视频免费观看| 亚洲成人av一区在线| 91精品啪在线免费| 黑人巨大精品欧美视频| 亚洲国产欧美一区二区三区久久| 一区二区三区 自拍偷拍| 午夜精品久久久久久99热| 夏目彩春在线中文字幕| 91亚洲手机在线视频播放| 一级黄片大鸡巴插入美女 | 在线成人日韩av电影| 精品成人啪啪18免费蜜臀| 3337p日本欧洲大胆色噜噜| 中文字幕在线第一页成人| 大香蕉大香蕉在线有码 av| 天堂女人av一区二区| 国产欧美日韩第三页| 都市激情校园春色狠狠| 人妻丝袜诱惑我操她视频| 最新97国产在线视频| 五十路人妻熟女av一区二区| 婷婷久久一区二区字幕网址你懂得| 亚洲熟色妇av日韩熟色妇在线| 粉嫩av蜜乳av蜜臀| 91国产在线视频免费观看| www骚国产精品视频| 欧美韩国日本国产亚洲| 99热99re在线播放| 99精品视频在线观看婷婷| 亚洲成a人片777777| 2021天天色天天干| 天天干天天操天天扣| 免费费一级特黄真人片| 国产精品久久久久久久精品视频| 精品一区二区三区三区色爱| 国产成人自拍视频在线免费观看| 久久农村老妇乱69系列| 天干天天天色天天日天天射| 日本熟妇喷水xxx| 成年人黄色片免费网站| 端庄人妻堕落挣扎沉沦| 精品一区二区三区三区色爱| 亚洲中文字幕校园春色| 在线观看911精品国产| 午夜大尺度无码福利视频| 欧美怡红院视频在线观看| 男人天堂最新地址av| 国产精品国色综合久久 | 国产又色又刺激在线视频| 青青伊人一精品视频| 久久尻中国美女视频| 国产日本欧美亚洲精品视| 久久艹在线观看视频| 视频一区二区三区高清在线| 亚洲综合色在线免费观看| 日本丰满熟妇BBXBBXHD| 欧美成人综合色在线噜噜| 国产黄色a级三级三级三级| 日本av高清免费网站| 欧美成一区二区三区四区| 天堂v男人视频在线观看| 999热精品视频在线| 天天操天天干天天插| 99精品国产免费久久| 亚洲综合自拍视频一区| 国产精品视频欧美一区二区| 91国内精品自线在拍白富美| 国产黄色大片在线免费播放| 国产女人露脸高潮对白视频| 2021天天色天天干| 最后99天全集在线观看| 影音先锋女人av噜噜色| 亚洲国产精品久久久久蜜桃| 中文字幕综合一区二区| 亚洲 欧美 自拍 偷拍 在线| 欧美视频一区免费在线| 在线观看的a站 最新| 水蜜桃国产一区二区三区| 精彩视频99免费在线| 国产又粗又黄又硬又爽| 欧美黑人巨大性xxxxx猛交| 在线视频这里只有精品自拍| 亚洲2021av天堂| 黄色片一级美女黄色片| 北条麻妃肉色丝袜视频| 91麻豆精品传媒国产黄色片| 在线观看黄色成年人网站| 福利国产视频在线观看| 92福利视频午夜1000看 | 夜色撩人久久7777| 97国产在线av精品| 精品少妇一二三视频在线| 国产在线91观看免费观看| 免费在线看的黄片视频| 亚洲va国产va欧美va在线| 四川五十路熟女av| 欧美日韩情色在线观看| mm131美女午夜爽爽爽| 欧洲亚洲欧美日韩综合| 日本www中文字幕| 人妻少妇性色欲欧美日韩| 国产精品久久久黄网站| 日韩精品一区二区三区在线播放| av男人天堂狠狠干| 中文字幕熟女人妻久久久| 日本黄色特一级视频| www,久久久,com| 91色九色porny| 人妻无码中文字幕专区| 亚洲 中文字幕在线 日韩| 顶级尤物粉嫩小尤物网站| 超黄超污网站在线观看| av中文字幕在线观看第三页 | 亚洲熟妇久久无码精品| 播放日本一区二区三区电影 | 91在线视频在线精品3| 成人色综合中文字幕| 97精品视频在线观看| 日韩a级精品一区二区| 在线免费观看国产精品黄色| 亚洲中文精品字幕在线观看 | 国产精品精品精品999| 黄色成年网站午夜在线观看| 国产日韩欧美视频在线导航 | 91麻豆精品传媒国产黄色片| 熟女妇女老妇一二三区| 久久久久久99国产精品| 日本阿v视频在线免费观看| 日本熟妇喷水xxx| 日韩三级黄色片网站| 92福利视频午夜1000看 | av一区二区三区人妻| 欧美视频不卡一区四区| gogo国模私拍视频| 1000小视频在线| 阴茎插到阴道里面的视频| 91精品国产高清自在线看香蕉网| 亚洲另类伦春色综合小| 国产一区av澳门在线观看| 新婚人妻聚会被中出| 欧美香蕉人妻精品一区二区| 91chinese在线视频| 亚洲专区激情在线观看视频| 视频久久久久久久人妻| 日韩美女综合中文字幕pp| 久久一区二区三区人妻欧美| 国产成人午夜精品福利| 91欧美在线免费观看| 天天干天天爱天天色| 人人爱人人妻人人澡39| 国产一区二区三免费视频| 亚洲乱码中文字幕在线| 国产超码片内射在线| 在线免费观看国产精品黄色| 又大又湿又爽又紧A视频| 青春草视频在线免费播放| 欧美精品资源在线观看| 亚洲免费国产在线日韩| 一区二区三区久久中文字幕| 18禁网站一区二区三区四区| 成年午夜影片国产片| 91九色porny国产蝌蚪视频| 香蕉片在线观看av| 一二三中文乱码亚洲乱码one | 欧美亚洲一二三区蜜臀| 亚洲国产成人无码麻豆艾秋| 欧美老妇精品另类不卡片| 国产一线二线三线的区别在哪| 成人性黑人一级av| 91 亚洲视频在线观看| 黄色av网站免费在线| 天天操天天爽天天干| 日韩亚国产欧美三级涩爱| 91高清成人在线视频| 色综合色综合色综合色| 精品一区二区三四区| 日本美女成人在线视频| 免费岛国喷水视频在线观看 | 成人av电影免费版| 青青草视频手机免费在线观看| 亚洲中文字幕国产日韩| 天天干天天操天天玩天天射| 换爱交换乱高清大片| 福利片区一区二体验区| 亚洲高清免费在线观看视频| 天天操夜夜骑日日摸| japanese日本熟妇另类| 啊用力插好舒服视频| h国产小视频福利在线观看| 狠狠鲁狠狠操天天晚上干干| 国产丰满熟女成人视频| 国产福利小视频大全| 一区二区三区综合视频| 亚洲一区二区三区久久受| 在线免费观看亚洲精品电影| 日韩成人综艺在线播放| 大胸性感美女羞爽操逼毛片| 亚洲高清国产拍青青草原| 天天插天天狠天天操| 亚洲伊人久久精品影院一美女洗澡| 91老熟女连续高潮对白| 激情内射在线免费观看| 唐人色亚洲av嫩草| 亚洲综合一区成人在线| 亚洲2021av天堂| 中国产一级黄片免费视频播放| av在线免费中文字幕| 色97视频在线播放| 99精品一区二区三区的区| 在线观看国产网站资源| 日本高清撒尿pissing| 老司机福利精品免费视频一区二区| 日韩av大胆在线观看| 亚洲国产精品免费在线观看| 在线不卡成人黄色精品| 国产高清在线观看1区2区| 51精品视频免费在线观看| 日韩激情文学在线视频| 美女吃鸡巴操逼高潮视频| 爱有来生高清在线中文字幕| 91啪国自产中文字幕在线| 国产日韩精品电影7777| 亚洲老熟妇日本老妇| 亚洲女人的天堂av| 精品人妻每日一部精品| 福利一二三在线视频观看| 动漫黑丝美女的鸡巴| 亚洲成人免费看电影| 国产成人精品久久二区91| 日本少妇高清视频xxxxx| 超污视频在线观看污污污| av俺也去在线播放| 粉嫩av蜜乳av蜜臀| 夜夜嗨av蜜臀av| 中文字幕—97超碰网| 绝色少妇高潮3在线观看| 国产亚洲天堂天天一区| 日本性感美女三级视频| 色av色婷婷人妻久久久精品高清| 亚洲嫩模一区二区三区| 中文字幕日本人妻中出| 国产亚洲精品视频合集| 中文字幕人妻一区二区视频| 91高清成人在线视频| 91成人在线观看免费视频| 首之国产AV医生和护士小芳| 亚洲码av无色中文| 亚洲午夜在线视频福利| 国产剧情演绎系列丝袜高跟| 在线观看成人国产电影| 喷水视频在线观看这里只有精品| 精品亚洲中文字幕av| 红杏久久av人妻一区| 亚洲国产精品美女在线观看| 精产国品久久一二三产区区别| 欧美日韩在线精品一区二区三| 97人人妻人人澡人人爽人人精品| 国产男女视频在线播放| 肏插流水妹子在线乐播下载| 中文字幕人妻av在线观看| 97国产在线av精品| 75国产综合在线视频| 亚洲av日韩精品久久久| 青青青艹视频在线观看| 1000小视频在线| 亚洲激情偷拍一区二区| 国产变态另类在线观看| 精品少妇一二三视频在线| 日韩一区二区电国产精品| 精品人妻伦一二三区久| 午夜精品福利一区二区三区p| 在线观看日韩激情视频| 免费在线看的黄网站| 欧美一区二区三区激情啪啪啪| 国产麻豆国语对白露脸剧情 | 91九色porny国产在线| 日本黄色三级高清视频| 9色在线视频免费观看| 久草视频在线免播放| 亚洲精品久久视频婷婷| 国产chinesehd精品麻豆| 2020国产在线不卡视频| 国产精品亚洲在线观看| 日本免费视频午夜福利视频| 三级av中文字幕在线观看| 91亚洲手机在线视频播放| 熟女视频一区,二区,三区| 午夜激情高清在线观看| 性欧美日本大妈母与子| 国产日本欧美亚洲精品视| 日韩精品啪啪视频一道免费| 日本www中文字幕| 在线观看911精品国产| 天天日天天爽天天爽| 日韩av有码中文字幕| 成人av天堂丝袜在线观看| 亚洲精品成人网久久久久久小说| av网址在线播放大全| 亚洲欧美一区二区三区电影| 福利视频一区二区三区筱慧| 青青草国内在线视频精选| 日本一区美女福利视频| 国产亚洲国产av网站在线| 久青青草视频手机在线免费观看| 久久久久久久亚洲午夜综合福利| 欧美精品欧美极品欧美视频 | 中文字幕高清在线免费播放| brazzers欧熟精品系列| 精品视频中文字幕在线播放 | 日韩美女精品视频在线观看网站 | 国产黄色高清资源在线免费观看| 97瑟瑟超碰在线香蕉| 狍和女人的王色毛片| 天码人妻一区二区三区在线看 | 亚洲综合在线视频可播放| 一区二区视频在线观看视频在线| 亚洲一区二区三区偷拍女厕91| yy6080国产在线视频| 国产亚洲成人免费在线观看 | 韩国黄色一级二级三级| 亚洲国产成人av在线一区| 欧美精品资源在线观看| 久久永久免费精品人妻专区 | 男人操女人逼逼视频网站| 精品久久婷婷免费视频| 天天日天天日天天擦| jul—619中文字幕在线| 老司机免费福利视频网| 中文字日产幕乱六区蜜桃| 欧美日韩v中文在线| 欧美日韩亚洲国产无线码| 亚洲男人在线天堂网| 红杏久久av人妻一区| 爱有来生高清在线中文字幕| h国产小视频福利在线观看| 福利一二三在线视频观看| 伊人情人综合成人久久网小说 | 亚洲图片偷拍自拍区| 国际av大片在线免费观看| 成人国产激情自拍三区| 99精品视频在线观看免费播放| 中文字幕奴隷色的舞台50| 亚洲成人av一区在线| 久久精品亚洲国产av香蕉| 国产刺激激情美女网站| 色综合久久五月色婷婷综合 | 中文字幕,亚洲人妻| 亚洲av成人网在线观看| 欧美天堂av无线av欧美| 黑人大几巴狂插日本少妇| 91桃色成人网络在线观看| 福利午夜视频在线观看| 538精品在线观看视频| 好太好爽好想要免费| 97香蕉碰碰人妻国产樱花| 日韩三级电影华丽的外出| 亚洲一区久久免费视频| 一级黄片大鸡巴插入美女| 黄色成年网站午夜在线观看| 欧美区一区二区三视频| 淫秽激情视频免费观看| 精品视频国产在线观看| 人人妻人人澡欧美91精品 | 大鸡吧插逼逼视频免费看| 精品国产成人亚洲午夜| 午夜影院在线观看视频羞羞羞| 91试看福利一分钟| 亚洲中文字幕乱码区| 亚洲欧美福利在线观看| 操的小逼流水的文章| 大白屁股精品视频国产| 狠狠操操操操操操操操操| 蜜臀av久久久久久久| 国产一区成人在线观看视频| jul—619中文字幕在线| 国产福利在线视频一区| 日韩北条麻妃一区在线| 人人妻人人澡人人爽人人dvl| 天天日天天爽天天干| 偷拍自拍福利视频在线观看| 特大黑人巨大xxxx| 精品亚洲国产中文自在线| 日本午夜福利免费视频| 99精品国自产在线人| 老司机你懂得福利视频| 大香蕉伊人国产在线| 韩国三级aaaaa高清视频| 精品欧美一区二区vr在线观看| 日韩美女福利视频网| 亚洲精品午夜aaa久久| 国产亚洲欧美45p| 日韩中文字幕在线播放第二页 | 欧美日韩人妻久久精品高清国产| 精品一区二区三区三区88| 性色av一区二区三区久久久| 插小穴高清无码中文字幕| 亚洲自拍偷拍精品网| 免费在线看的黄片视频| 天天日天天爽天天干| 100%美女蜜桃视频| 亚洲精品 欧美日韩| 日本少妇精品免费视频| 免费黄页网站4188| 五月精品丁香久久久久福利社| 在线成人日韩av电影| 免费观看国产综合视频| 丰满的子国产在线观看| 免费成人va在线观看| nagger可以指黑人吗| 亚洲一区av中文字幕在线观看| 亚洲av午夜免费观看| 亚洲人妻30pwc| 国产精品自拍偷拍a| 91九色porny蝌蚪国产成人| 日日夜夜大香蕉伊人| 一区二区三区久久久91| 夫妻在线观看视频91| 在线亚洲天堂色播av电影| 喷水视频在线观看这里只有精品| 亚洲欧美另类手机在线| 一区二区三区国产精选在线播放| 中文字幕—97超碰网| 大肉大捧一进一出好爽在线视频| 在线观看日韩激情视频| 青青青激情在线观看视频| 久久99久久99精品影院| 国产又粗又硬又大视频| 熟妇一区二区三区高清版| 大香蕉日本伊人中文在线| 日本少妇高清视频xxxxx| 午夜精品一区二区三区城中村| 中国视频一区二区三区| 男女啪啪视频免费在线观看| 亚洲狠狠婷婷综合久久app| 天天干天天操天天玩天天射| 午夜精品在线视频一区| 天堂av在线最新版在线| 国产伦精品一区二区三区竹菊| 夜夜骑夜夜操夜夜奸| 91人妻精品一区二区久久| 美女福利视频网址导航| 毛片一级完整版免费| 99热这里只有精品中文| 四川乱子伦视频国产vip| 一区二区三区四区五区性感视频| 日韩欧美一级精品在线观看| 做爰视频毛片下载蜜桃视频1| 夜夜嗨av蜜臀av| 青青青青草手机在线视频免费看| 亚洲va国产va欧美精品88| 视频在线免费观看你懂得| 粉嫩av蜜乳av蜜臀| 亚洲中文字幕乱码区| 在线不卡日韩视频播放| 黑人性生活视频免费看| 欧美综合婷婷欧美综合| 在线不卡成人黄色精品| 国产精品女邻居小骚货| 国产精品国产三级麻豆| 午夜久久香蕉电影网| 国产精品欧美日韩区二区| 99人妻视频免费在线| 免费在线福利小视频| 国产精品黄大片在线播放| 91精品综合久久久久3d动漫| 91精品高清一区二区三区| 久久久91蜜桃精品ad| 97超碰国语国产97超碰| 日本高清成人一区二区三区| 色吉吉影音天天干天天操| 在线播放一区二区三区Av无码| 男人的网址你懂的亚洲欧洲av| 青草亚洲视频在线观看| 日本一区二区三区免费小视频| 黄色录像鸡巴插进去| 在线不卡成人黄色精品| 国产使劲操在线播放| 一区二区在线观看少妇| 日本阿v视频在线免费观看| 欧美成人黄片一区二区三区| 亚洲熟妇无码一区二区三区| 欧美亚洲一二三区蜜臀| 日本福利午夜电影在线观看| 黄色av网站免费在线| 国产美女午夜福利久久| 日韩av有码中文字幕| 欧美亚洲国产成人免费在线| 蜜桃色婷婷久久久福利在线| 亚洲欧洲av天堂综合| 午夜精品亚洲精品五月色| 人妻av无码专区久久绿巨人| 韩国女主播精品视频网站| 国产视频在线视频播放| 中文字幕视频一区二区在线观看| 直接观看免费黄网站| 亚洲熟女女同志女同| 亚洲一区av中文字幕在线观看| 人妻素人精油按摩中出| 中文字幕一区二区三区蜜月| 天天干天天插天天谢| www骚国产精品视频| av破解版在线观看| 中文字幕一区二区三区人妻大片| 韩国男女黄色在线观看| 日日操夜夜撸天天干| 在线观看欧美黄片一区二区三区| 欧美久久一区二区伊人| 精品成人啪啪18免费蜜臀| 成人av在线资源网站| 日韩熟女av天堂系列| 天天干天天啪天天舔| 丰满少妇人妻xxxxx| 成人sm视频在线观看| 国产女人被做到高潮免费视频 | 亚洲天堂精品福利成人av| 久久久久只精品国产三级| 国产精品视频欧美一区二区 | 春色激情网欧美成人| 五十路熟女人妻一区二区9933| 97精品视频在线观看| 中文字幕亚洲中文字幕| 区一区二区三国产中文字幕| 午夜久久久久久久精品熟女| 国产成人午夜精品福利| 亚洲视频在线视频看视频在线| 又粗又长 明星操逼小视频| 亚洲欧美福利在线观看| 风流唐伯虎电视剧在线观看| 欧美亚洲少妇福利视频| 一级黄片久久久久久久久| 国产精品sm调教视频| 国产精品视频欧美一区二区| 2021最新热播中文字幕| 福利国产视频在线观看| 日韩美在线观看视频黄| 97国产在线观看高清| 中文字幕最新久久久| 婷婷午夜国产精品久久久| 中文字幕中文字幕人妻| 55夜色66夜色国产精品站| 亚洲麻豆一区二区三区| 日本少妇人妻xxxxx18| 成年人的在线免费视频| 一级黄片久久久久久久久| av中文字幕国产在线观看| 欧美日韩人妻久久精品高清国产| 亚洲欧美人精品高清| 天天日天天摸天天爱| 少妇被强干到高潮视频在线观看| 中文字幕欧美日韩射射一| 午夜毛片不卡在线看| 天天干天天操天天摸天天射| 午夜av一区二区三区| 在线播放一区二区三区Av无码| 午夜在线一区二区免费| av天堂中文字幕最新| 日本www中文字幕| 午夜蜜桃一区二区三区| 国产性生活中老年人视频网站| 天堂av狠狠操蜜桃| 免费无码人妻日韩精品一区二区| 欧美80老妇人性视频| 93视频一区二区三区| 亚洲粉嫩av一区二区三区| 在线播放国产黄色av| 亚洲高清自偷揄拍自拍| 国语对白xxxx乱大交| 精品久久久久久高潮| 欧美精品国产综合久久| 国产午夜福利av导航| 免费av岛国天堂网站| 精品视频中文字幕在线播放| 被大鸡吧操的好舒服视频免费| 中文字幕在线免费第一页| 在线 中文字幕 一区| 91国产在线视频免费观看| 欧美性受xx黑人性猛交| 中文字幕人妻av在线观看| 91国内精品自线在拍白富美| 精品亚洲中文字幕av| 在线免费91激情四射| 久草视频在线看免费| 天天干天天操天天插天天日| 日韩三级黄色片网站| 亚洲一区二区三区久久午夜 | 精品一区二区三四区| 91麻豆精品秘密入口在线观看| 一区二区三区麻豆福利视频| 午夜成午夜成年片在线观看| 成人影片高清在线观看| 日韩成人免费电影二区| jiujiure精品视频在线| 天天躁日日躁狠狠躁av麻豆| 久久国产精品精品美女| 久草免费人妻视频在线| 揄拍成人国产精品免费看视频| 国产91精品拍在线观看| 一级黄片大鸡巴插入美女| 蝴蝶伊人久久中文娱乐网| 人妻无码中文字幕专区| 成人高清在线观看视频| 99热色原网这里只有精品| 亚洲成人av一区在线| 视频 国产 精品 熟女 | 都市家庭人妻激情自拍视频| 黄色男人的天堂视频| 又粗又硬又猛又黄免费30| 国产精品久久久久久久久福交| 亚洲成人av一区久久| 一区二区三区欧美日韩高清播放| 9l人妻人人爽人人爽| 亚洲天堂成人在线观看视频网站| 欧美日韩国产一区二区三区三州| 99re久久这里都是精品视频| 亚洲色偷偷综合亚洲AV伊人 | 80电影天堂网官网| 天天操天天干天天日狠狠插| 亚洲欧美成人综合在线观看| 黄色录像鸡巴插进去| 欧洲欧美日韩国产在线| 欧美偷拍亚洲一区二区| 国产久久久精品毛片| 黑人3p华裔熟女普通话| 1769国产精品视频免费观看| 午夜极品美女福利视频| 午夜免费观看精品视频| 亚洲无码一区在线影院| 99婷婷在线观看视频| 欧美日韩熟女一区二区三区| 国产日韩一区二区在线看| 91老熟女连续高潮对白| 男人插女人视频网站| 2019av在线视频| 日本熟妇色熟妇在线观看| 亚洲欧美国产综合777| 在线免费观看欧美小视频| 91一区精品在线观看| 久久麻豆亚洲精品av| 亚洲一区制服丝袜美腿| 欧美亚洲免费视频观看| 天天日天天操天天摸天天舔| 亚洲人妻视频在线网| 97瑟瑟超碰在线香蕉| 国产麻豆剧传媒精品国产av蜜桃| 欧美一区二区中文字幕电影| 91片黄在线观看喷潮| 午夜精彩视频免费一区| 精品人妻每日一部精品| 日本熟妇喷水xxx| 78色精品一区二区三区| 午夜在线观看一区视频| 欧美80老妇人性视频| 一区二区三区美女毛片| 综合国产成人在线观看| 小泽玛利亚视频在线观看| 熟女视频一区,二区,三区| 不戴胸罩引我诱的隔壁的人妻| 亚洲高清国产一区二区三区| 中文字幕一区二区人妻电影冢本| 日本人妻少妇18—xx| 国产va在线观看精品| 最新国产精品网址在线观看| 日本男女操逼视频免费看| 日本少妇人妻xxxxx18| 超级av免费观看一区二区三区| 天天插天天色天天日| 一区二区三区四区五区性感视频| 99热99这里精品6国产| 中国产一级黄片免费视频播放| 天天射,天天操,天天说| 老鸭窝在线观看一区| 日本av在线一区二区三区| 高潮视频在线快速观看国家快速| 大香蕉伊人中文字幕| 97国产在线观看高清| 亚洲国产成人av在线一区| 日本脱亚入欧是指什么| 国内资源最丰富的网站| 精品久久久久久久久久中文蒉| 日本欧美视频在线观看三区| 精品人妻一二三区久久| 天天日夜夜干天天操| 97超碰免费在线视频| 人妻丝袜av在线播放网址| 在线免费观看靠比视频的网站| 在线免费观看av日韩| 精品国产午夜视频一区二区| 2020久久躁狠狠躁夜夜躁| 一区二区三区的久久的蜜桃的视频| 亚洲成人av一区在线| 亚洲综合图片20p| 亚洲精品亚洲人成在线导航| 中文字幕在线观看国产片| 日本特级片中文字幕| 亚洲人妻av毛片在线| 久久久久久97三级| 亚洲一区制服丝袜美腿| 做爰视频毛片下载蜜桃视频1| 天天日天天鲁天天操| 婷婷午夜国产精品久久久| 欧美另类z0z变态| 国产精品三级三级三级| 中文字幕熟女人妻久久久| 美女骚逼日出水来了| 蜜桃色婷婷久久久福利在线| 天天日天天天天天天天天天天| 国产av自拍偷拍盛宴| 国产精品人久久久久久| 久草视频首页在线观看| 老有所依在线观看完整版 | 2020中文字幕在线播放| 男人的天堂在线黄色| 精品高潮呻吟久久av| 老司机在线精品福利视频| 天堂女人av一区二区| 扒开让我视频在线观看| 521精品视频在线观看| 操人妻嗷嗷叫视频一区二区 | huangse网站在线观看| 好吊操视频这里只有精品| 国产精品日韩欧美一区二区| 亚洲av日韩av第一区二区三区| 99精品免费观看视频| 中文字幕在线观看极品视频| 日韩人妻在线视频免费| 亚洲一区久久免费视频| 国产日韩av一区二区在线| 亚洲av日韩精品久久久| 国产成人午夜精品福利| 青青热久免费精品视频在线观看 | 最近中文字幕国产在线| 人妻少妇性色欲欧美日韩| 色天天天天射天天舔| 年轻的人妻被夫上司侵犯| 在线免费观看视频一二区| 福利视频一区二区三区筱慧| 成人sm视频在线观看| 国产真实乱子伦a视频| 三级av中文字幕在线观看| 日日夜夜大香蕉伊人| 熟女视频一区,二区,三区| 韩国三级aaaaa高清视频 | 人妻无码色噜噜狠狠狠狠色| 强行扒开双腿猛烈进入免费版| 欧美综合婷婷欧美综合| 大香蕉日本伊人中文在线| 午夜久久久久久久99| 韩国黄色一级二级三级| 人妻少妇精品久久久久久| 少妇高潮无套内谢麻豆| 亚洲精品成人网久久久久久小说| 2021天天色天天干| 欧美国品一二三产区区别| 天天干天天操天天摸天天射| 日本精品一区二区三区在线视频。| 一本久久精品一区二区| 久久国产精品精品美女| 女人精品内射国产99| 国产综合视频在线看片| 国产aⅴ一线在线观看| 日曰摸日日碰夜夜爽歪歪| 视频 国产 精品 熟女 | 在线国产日韩欧美视频| 在线 中文字幕 一区| 夜女神免费福利视频| 国产成人无码精品久久久电影| 青青草原网站在线观看| 青青青青在线视频免费观看| 亚洲公开视频在线观看| 亚洲熟女女同志女同| 91国内精品自线在拍白富美| 欧美成人猛片aaaaaaa| 美女张开两腿让男人桶av| 天天摸天天干天天操科普| 天堂v男人视频在线观看| 女警官打开双腿沦为性奴| 亚洲青青操骚货在线视频| 日本成人一区二区不卡免费在线| 啊用力插好舒服视频| 日日夜夜狠狠干视频| 欧美 亚洲 另类综合| 欧美3p在线观看一区二区三区| 最新91精品视频在线| 亚洲国产香蕉视频在线播放| 婷婷久久久综合中文字幕| 专门看国产熟妇的网站| 日本熟女50视频免费| 自拍偷拍亚洲精品第2页| 天堂va蜜桃一区入口| 成人亚洲精品国产精品| 欧美老鸡巴日小嫩逼| 精品日产卡一卡二卡国色天香| 日韩精品一区二区三区在线播放| 日本熟妇色熟妇在线观看| 91九色porny国产蝌蚪视频| 1769国产精品视频免费观看| 五月天久久激情视频| 黄色的网站在线免费看| 日本少妇精品免费视频| 91精品资源免费观看| 国产精品欧美日韩区二区| 国产成人精品一区在线观看| heyzo蜜桃熟女人妻| 亚洲偷自拍高清视频| 蜜桃色婷婷久久久福利在线| av高潮迭起在线观看| 亚洲激情唯美亚洲激情图片| 青青伊人一精品视频| 国产一线二线三线的区别在哪 | 国产精品视频男人的天堂| 特大黑人巨大xxxx|