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

RESTful API設計最佳實踐

開發 項目管理
網上的很多關于API設計的觀點都十分”學院派“,它們也許更有理論基礎,但是有時卻和現實世界脫軌(因此我是自由派)。所以我這篇文章的目標是從實踐的角度出發,給出當前網絡應用的API設計最佳實踐(當然,是我認為的最佳了~),如果覺得不合適,我不會遵從標準。

背景

目前互聯網上充斥著大量的關于RESTful API(為了方便,以后API和RESTful API 一個意思)如何設計的文章,然而卻沒有一個”萬能“的設計標準:如何鑒權?API格式如何?你的API是否應該加入版本信息?當你開始寫一個app的時候,特別是后端模型部分已經寫完的時候,你不得不殫精竭慮的設計和實現自己app的public API部分。因為一旦發布,對外發布的API將會很難改變。

在給SupportedFu設計API的時候,我試圖以實用的角度來解決上面提到的問題。我希望可以設計出容易使用,容易部署,并且足夠靈活的API,本文因此而生。

API設計的基本要求

網上的很多關于API設計的觀點都十分”學院派“,它們也許更有理論基礎,但是有時卻和現實世界脫軌(因此我是自由派)。所以我這篇文章的目標是從實踐的角度出發,給出當前網絡應用的API設計最佳實踐(當然,是我認為的最佳了~),如果覺得不合適,我不會遵從標準。當然作為設計的基礎,幾個必須的原則還是要遵守的:

  1. 當標準合理的時候遵守標準。
  2. API應該對程序員友好,并且在瀏覽器地址欄容易輸入。
  3. API應該簡單,直觀,容易使用的同時優雅。
  4. API應該具有足夠的靈活性來支持上層ui。
  5. API設計權衡上述幾個原則。

需要強調的是:API的就是程序員的UI,和其他UI一樣,你必須仔細考慮它的用戶體驗!

使用RESTful URLs 和action.

雖然前面我說沒有一個萬能的API設計標準。但確實有一個被普遍承認和遵守:RESTfu設計原則。它被Roy Felding提出(在他的”基于網絡的軟件架構“論文中第五章)。而REST的核心原則是將你的API拆分為邏輯上的資源。這些資源通過http被操作(GET ,POST,PUT,DELETE)。

那么我應該如何拆分出這些資源呢?

顯然從API用戶的角度來看,”資源“應該是個名詞。即使你的內部數據模型和資源已經有了很好的對應,API設計的時候你仍然不需要把它們一對一的都暴露出來。這里的關鍵是隱藏內部資源,暴露必需的外部資源。

在SupportFu里,資源是 ticket、user、group。

一旦定義好了要暴露的資源,你可以定義資源上允許的操作,以及這些操作和你的API的對應關系:

  • GET /tickets # 獲取ticket列表
  • GET /tickets/12 # 查看某個具體的ticket
  • POST /tickets # 新建一個ticket
  • PUT /tickets/12 # 更新ticket 12.
  • DELETE /tickets/12 #刪除ticekt 12

可以看出使用REST的好處在于可以充分利用http的強大實現對資源的CURD功能。而這里你只需要一個endpoint:/tickets,再沒有其他什么命名規則和url規則了,cool!

這個endpoint的單數復數

一個可以遵從的規則是:雖然看起來使用復數來描述某一個資源實例看起來別扭,但是統一所有的endpoint,使用復數使得你的URL更加規整。這讓API使用者更加容易理解,對開發者來說也更容易實現。

如何處理關聯?關于如何處理資源之間的管理REST原則也有相關的描述:

  • GET /tickets/12/messages- Retrieves list of messages for ticket #12
  • GET /tickets/12/messages/5- Retrieves message #5 for ticket #12
  • POST /tickets/12/messages- Creates a new message in ticket #12
  • PUT /tickets/12/messages/5- Updates message #5 for ticket #12
  • PATCH /tickets/12/messages/5- Partially updates message #5 for ticket #12
  • DELETE /tickets/12/messages/5- Deletes message #5 for ticket #12

其中,如果這種關聯和資源獨立,那么我們可以在資源的輸出表示中保存相應資源的endpoint。然后API的使用者就可以通過點擊鏈接找到相關的資源。如果關聯和資源聯系緊密。資源的輸出表示就應該直接保存相應資源信息。(例如這里如果message資源是獨立存在的,那么上面 GET /tickets/12/messages就會返回相應message的鏈接;相反的如果message不獨立存在,他和ticket依附存在,則上面的 API調用返回直接返回message信息)

不符合CURD的操作

對這個令人困惑的問題,下面是一些解決方法:

  1. 重構你的行為action。當你的行為不需要參數的時候,你可以把active對應到activated這個資源,(更新使用patch).
  2. 以子資源對待。例如:GitHub上,對一個gists加星操作:PUT /gists/:id/star 并且取消星操作:DELETE /gists/:id/star.
  3. 有時候action實在沒有難以和某個資源對應上例如search。那就這么辦吧。我認為API的使用者對于/search這種url也不會有太大意見的(畢竟他很容易理解)。只要注意在文檔中寫清楚就可以了。
  4.  

永遠使用SSL

毫無例外,永遠都要使用SSL。你的應用不知道要被誰,以及什么情況訪問。有些是安全的,有些不是。使用SSL可以減少鑒權的成本:你只需要一個簡單的令牌(token)就可以鑒權了,而不是每次讓用戶對每次請求簽名。

值得注意的是:不要讓非SSL的url訪問重定向到SSL的url。

文檔

文檔和API本身一樣重要。文檔應該容易找到,并且公開(把它們藏到pdf里面或者存到需要登錄的地方都不太好)。文檔應該有展示請求和輸出的例子:或者以點擊鏈接的方式或者通過curl的方式(請見openstack的文檔)。如果有更新(特別是公開的API),應該及時更新文檔。文檔中應該有關于何時棄用某個API的時間表以及詳情。使用郵件列表或者博客記錄是好方法。

版本化

在API上加入版本信息可以有效的防止用戶訪問已經更新了的API,同時也能讓不同主要版本之間平穩過渡。關于是否將版本信息放入url還是放入請求頭有過爭論:API version should be included in the URL or in a header. 學術界說它應該放到header里面去,但是如果放到url里面我們就可以跨版本的訪問資源了。。(參考openstack)。

strip使用的方法就很好:它的url里面有主版本信息,同時請求頭倆面有子版本信息。這樣在子版本變化過程中url的穩定的。變化有時是不可避免的,關鍵是如何管理變化。完整的文檔和合理的時間表都會使得API使用者使用的更加輕松。

結果過濾,排序,搜索:

url最好越簡短越好,和結果過濾,排序,搜索相關的功能都應該通過參數實現(并且也很容易實現)。

過濾:為所有提供過濾功能的接口提供統一的參數。例如:你想限制get /tickets 的返回結果:只返回那些open狀態的ticket–get /tickektsstate=open這里的state就是過濾參數。

排序:和過濾一樣,一個好的排序參數應該能夠描述排序規則,而不業務相關。復雜的排序規則應該通過組合實現:

  • GET /ticketssort=-priority- Retrieves a list of tickets in descending order of priority
  • GET /ticketssort=-priority,created_at- Retrieves a list of tickets in descending order of priority. Within a specific priority, older tickets are ordered first

這里第二條查詢中,排序規則有多個rule以逗號間隔組合而成。

搜索:有些時候簡單的排序是不夠的。我們可以使用搜索技術(ElasticSearch和Lucene)來實現(依舊可以作為url的參數)。

  • GET /ticketsq=return&state=open&sort=-priority,created_at- Retrieve the highest priority open tickets mentioning the word ‘return’

對于經常使用的搜索查詢,我們可以為他們設立別名,這樣會讓API更加優雅。例如:
get /ticketsq=recently_closed -> get /tickets/recently_closed.

限制API返回值的域

有時候API使用者不需要所有的結果,在進行橫向限制的時候(例如值返回API結果的前十項)還應該可以進行縱向限制。并且這個功能能有效的提高網絡帶寬使用率和速度。可以使用fields查詢參數來限制返回的域例如:
GET /ticketsfields=id,subject,customer_name,updated_at&state=open&sort=-updated_at

更新和創建操作應該返回資源

PUT、POST、PATCH 操作在對資源進行操作的時候常常有一些副作用:例如created_at,updated_at 時間戳。為了防止用戶多次的API調用(為了進行此次的更新操作),我們應該會返回更新的資源(updated representation.)例如:在POST操作以后,返回201 created 狀態碼,并且包含一個指向新資源的url作為返回頭

是否需要 “HATEOAS

網上關于是否允許用戶創建新的url有很大的異議(注意不是創建資源產生的url)。為此REST制定了HATEOAS來描述了和endpoint進行交互的時候,行為應該在資源的metadata返回值里面進行定義。

(譯注:作者這里認為HATEOAS還不算成熟,我也不怎么理解這段就算了,讀者感興趣可以自己去原文查看)

只提供json作為返回格式

現在開始比較一下XML和json了。XML即冗長,難以閱讀,又不適合各種編程語言解析。當然XML有擴展性的優勢,但是如果你只是將它來對內部資源串行化,那么他的擴展優勢也發揮不出來。很多應用(youtube,twitter,box)都已經開始拋棄XML了,我也不想多費口舌。給了google上的趨勢圖吧:

當然如果的你使用用戶里面企業用戶居多,那么可能需要支持XML。如果是這樣的話你還有另外一個問題:你的http請求中的media類型是應該和 accept 頭同步還是和url?為了方便(browser explorability),應該是在url中(用戶只要自己拼url就好了)。如果這樣的話最好的方法是使用.xml或者.json的后綴。

命名方式?

是蛇形命令(下劃線和小寫)還是駝峰命名?如果使用json那么最好的應該是遵守JAVASCRIPT的命名方法-也就是說駱駝命名法。如果你正在使用多種語言寫一個庫,那么最好按照那些語言所推薦的,java,c#使用駱駝,python,ruby使用snake。

個人意見:我總覺得蛇形命令更好使一些,當然這沒有什么理論的依據。有人說蛇形命名讀起來更快,能達到20%,也不知道真假http://ieeexplore.ieee.org/xpl/articleDetails.jsptp=&arnumber=5521745

默認使用pretty print格式,使用gzip

只是使用空格的返回結果從瀏覽器上看總是覺得很惡心(一大坨有沒有?~)。當然你可以提供url上的參數來控制使用“pretty print”,但是默認開啟這個選項還是更加友好。格外的傳輸上的損失不會太大。相反你如果忘了使用gzip那么傳輸效率將會大大減少,損失大大增加。想象一個用戶正在debug那么默認的輸出就是可讀的-而不用將結果拷貝到其他什么軟件中在格式化-是想起來就很爽的事,不是么?

下面是一個例子:

$ curl https://API.github.com/users/veesahni > with-whitespace.txt
$ ruby -r json -e 'puts JSON JSON.parse(STDIN.read)' < with-whitespace.txt > without-whitespace.txt
$ gzip -c with-whitespace.txt > with-whitespace.txt.gz
$ gzip -c without-whitespace.txt > without-whitespace.txt.gz

輸出如下:

  • without-whitespace.txt- 1252 bytes
  • with-whitespace.txt- 1369 bytes
  • without-whitespace.txt.gz- 496 bytes
  • with-whitespace.txt.gz- 509 bytes

在上面的例子中,多余的空格使得結果大小多出了8.5%(沒有使用gzip),相反只多出了2.6%。據說:twitter使用gzip之后它的 streaming API傳輸減少了80%(link:https://dev.twitter.com/blog/announcing-gzip- compression-streaming-APIs).

只在需要的時候使用“envelope”

很多API象下面這樣返回結果:

  1. {  
  2.   "data" : {  
  3.     "id" : 123,  
  4.     "name" : "John" 
  5.   }  

理由很簡單:這樣做可以很容易擴展返回結果,你可以加入一些分頁信息,一些數據的元信息等-這對于那些不容易訪問到返回頭的API使用者來說確實有用,但是隨著“標準”的發展(cors和http://tools.ietf.org/html/rfc5988#page-6都開始被加入到標準中了),我個人推薦不要那么做。

何時使用envelope?

有兩種情況是應該使用envelope的。如果API使用者確實無法訪問返回頭,或者API需要支持交叉域請求(通過jsonp)。
jsonp請求在請求的url中包含了一個callback函數參數。如果給出了這個參數,那么API應該返回200,并且把真正的狀態碼放到返回值里面(包裝在信封里),例如:

  1. callback_function({  
  2.   status_code: 200,  
  3.   next_page: "https://..",  
  4.   response: {  
  5.     ... actual JSON response body ...   
  6.   }  
  7. }) 

同樣為了支持無法方法返回頭的API使用者,可以允許envelope=true這樣的參數。

#p#

在post,put,patch上使用json作為輸入

如果你認同我上面說的,那么你應該決定使用json作為所有的API輸出格式,那么我們接下來考慮考慮API的輸入數據格式。
很多的API使用url編碼格式:就像是url查詢參數的格式一樣:單純的鍵值對。這種方法簡單有效,但是也有自己的問題:它沒有數據類型的概念。這使得程序不得不根據字符串解析出布爾和整數,而且還沒有層次結構–雖然有一些關于層次結構信息的約定存在可是和本身就支持層次結構的json比較一下還是不很好用。

當然如果API本身就很簡單,那么使用url格式的輸入沒什么問題。但對于復雜的API你應該使用json。或者干脆統一使用json。
注意使用json傳輸的時候,要求請求頭里面加入:Content-Type:applicatin/json.否則拋出415異常(unsupported media type)。

分頁

分頁數據可以放到“信封”里面,但隨著標準的改進,現在我推薦將分頁信息放到link header里面:http://tools.ietf.org/html/rfc5988#page-6。

使用link header的API應該返回一系列組合好了的url而不是讓用戶自己再去拼。這點在基于游標的分頁中尤為重要。例如下面,來自github的文檔

  1. Link: <https://api.github.com/user/repos?page=3&per_page=100>rel="next",   
  2. <https://api.github.com/user/repos?page=50&per_page=100>rel="last" 

自動加載相關的資源

很多時候,自動加載相關資源非常有用,可以很大的提高效率。但是這卻和RESTful的原則相背。為了如此,我們可以在url中添加參數:embed(或者expend)。embed可以是一個逗號分隔的串,例如:

  1. GET /ticket/12embed=customer.name,assigned_user 

對應的API返回值如下:

  1. {  
  2.   "id" : 12,  
  3.   "subject" : "I have a question!",  
  4.   "summary" : "Hi, ....",  
  5.   "customer" : {  
  6.     "name" : "Bob" 
  7.   },  
  8.   assigned_user: {  
  9.    "id" : 42,  
  10.    "name" : "Jim",  
  11.   }  

值得提醒的是,這個功能有時候會很復雜,并且可能導致N+1 SELECT 問題

重寫HTTP方法

有的客戶端只能發出簡單的GET 和POST請求。為了照顧他們,我們可以重寫HTTP請求。這里沒有什么標準,但是一個普遍的方式是接受X-HTTP-Method-Override請求頭。

速度限制

為了避免請求泛濫,給API設置速度限制很重要。為此 RFC 6585 引入了HTTP狀態碼429(too many requests)。加入速度設置之后,應該提示用戶,至于如何提示標準上沒有說明,不過流行的方法是使用HTTP的返回頭。

下面是幾個必須的返回頭(依照twitter的命名規則):

  • X-Rate-Limit-Limit :當前時間段允許的并發請求數
  • X-Rate-Limit-Remaining:當前時間段保留的請求數。
  • X-Rate-Limit-Reset:當前時間段剩余秒數

為什么使用當前時間段剩余秒數而不是時間戳?

時間戳保存的信息很多,但是也包含了很多不必要的信息,用戶只需要知道還剩幾秒就可以再發請求了這樣也避免了clock skew問題

有些API使用UNIX格式時間戳,我建議不要那么干。為什么?HTTP 已經規定了使用 RFC 1123 時間格式

鑒權 Authentication

restful API是無狀態的也就是說用戶請求的鑒權和cookie以及session無關,每一次請求都應該包含鑒權證明。

通過使用ssl我們可以不用每次都提供用戶名和密碼:我們可以給用戶返回一個隨機產生的token。這樣可以極大的方便使用瀏覽器訪問API的用戶。這種方法適用于用戶可以首先通過一次用戶名-密碼的驗證并得到token,并且可以拷貝返回的token到以后的請求中。如果不方便,可以使用 OAuth 2來進行token的安全傳輸。

支持jsonp的API需要額外的鑒權方法,因為jsonp請求無法發送普通的credential。這種情況下可以在查詢url中添加參數:access_token。注意使用url參數的問題是:目前大部分的網絡服務器都會講query參數保存到服務器日志中,這可能會成為大的安全風險。

注意上面說到的只是三種傳輸token的方法,實際傳輸的token可能是一樣的。

緩存

HTTP提供了自帶的緩存框架。你需要做的是在返回的時候加入一些返回頭信息,在接受輸入的時候加入輸入驗證。基本兩種方法:

ETag:當生成請求的時候,在HTTP頭里面加入ETag,其中包含請求的校驗和和哈希值,這個值和在輸入變化的時候也應該變化。如果輸入的HTTP請求包含IF-NONE-MATCH頭以及一個ETag值,那么API應該返回304 not modified狀態碼,而不是常規的輸出結果。

Last-Modified:和etag一樣,只是多了一個時間戳。返回頭里的Last-Modified:包含了 RFC 1123 時間戳,它和IF-MODIFIED-SINCE一致。HTTP規范里面有三種date格式,服務器應該都能處理。

出錯處理

就像html錯誤頁面能夠顯示錯誤信息一樣,API 也應該能返回可讀的錯誤信息–它應該和一般的資源格式一致。API應該始終返回相應的狀態碼,以反映服務器或者請求的狀態。API的錯誤碼可以分為兩部分,400系列和500系列,400系列表明客戶端錯誤:如錯誤的請求格式等。500系列表示服務器錯誤。API應該至少將所有的400系列的錯誤以 json形式返回。如果可能500系列的錯誤也應該如此。json格式的錯誤應該包含以下信息:一個有用的錯誤信息,一個唯一的錯誤碼,以及任何可能的詳細錯誤描述。如下:

  1. {  
  2.   "code" : 1234,  
  3.   "message" : "Something bad happened <img src="http://blog.jobbole.com/wp-includes/images/smilies/icon_sad.gif" alt=":-(" class="wp-smiley"> ",  
  4.   "description" : "More details about the error here" 

對PUT,POST,PATCH的輸入的校驗也應該返回相應的錯誤信息,例如:

  1. {  
  2.   "code" : 1024,  
  3.   "message" : "Validation Failed",  
  4.   "errors" : [  
  5.     {  
  6.       "code" : 5432,  
  7.       "field" : "first_name",  
  8.       "message" : "First name cannot have fancy characters" 
  9.     },  
  10.     {  
  11.        "code" : 5622,  
  12.        "field" : "password",  
  13.        "message" : "Password cannot be blank" 
  14.     }  
  15.   ]  

HTTP 狀態碼

  1. 200 ok  - 成功返回狀態,對應,GET,PUT,PATCH,DELETE.  
  2. 201 created  - 成功創建。  
  3. 304 not modified   - HTTP緩存有效。  
  4. 400 bad request   - 請求格式錯誤。  
  5. 401 unauthorized   - 未授權。  
  6. 403 forbidden   - 鑒權成功,但是該用戶沒有權限。  
  7. 404 not found - 請求的資源不存在  
  8. 405 method not allowed - 該http方法不被允許。  
  9. 410 gone - 這個url對應的資源現在不可用。  
  10. 415 unsupported media type - 請求類型錯誤。  
  11. 422 unprocessable entity - 校驗錯誤時用。  
  12. 429 too many request - 請求過多。 

英文原文:appdesignvault,編譯:@奇風余谷

譯文鏈接:http://blog.jobbole.com/40931/

責任編輯:林師授 來源: 伯樂在線
相關推薦

2017-03-13 14:09:19

RESTful API實踐

2016-12-27 08:49:55

API設計策略

2022-05-13 08:17:05

HTTPRESTful架構

2023-11-07 07:08:57

2016-12-30 14:47:21

設計RESTfulAPI

2014-04-18 10:58:44

AndroidAPI實踐

2010-12-28 10:12:39

PHP

2024-06-27 10:48:48

2018-12-04 09:00:00

API安全性令牌

2019-01-21 14:20:26

Java開發代碼

2024-09-03 08:24:52

RestfulAPI結構

2009-06-22 14:48:21

DRY架構設計

2009-07-07 16:13:39

JDK日志

2017-04-27 10:33:50

云計算

2023-04-14 12:23:15

2017-10-20 08:25:10

數據收集工具數據源

2022-02-10 23:38:23

API架構設計

2011-08-18 11:05:21

jQuery

2023-07-21 01:12:30

Reactfalse?變量

2023-12-06 07:13:16

RESTAPI客戶端
點贊
收藏

51CTO技術棧公眾號

污污视频在线免费看| 91精品人妻一区二区| 黄页网站大全在线免费观看| 九九亚洲视频| 日韩专区欧美专区| 久久精品国产成人| 亚洲精品乱码久久| 欧美另类激情| 精品久久在线播放| 色乱码一区二区三区熟女 | 一本色道久久加勒比精品| 亚洲日本无吗高清不卡| 开心激情综合网| 久久国产三级精品| 538国产精品一区二区免费视频| 四虎成人免费影院| 大奶在线精品| 正在播放亚洲一区| 精品www久久久久奶水| 99福利在线| 国产人成亚洲第一网站在线播放| 99re视频| 国产又粗又猛又爽| 日韩国产在线观看| **欧美日韩vr在线| 成人免费看片98| 欧美gvvideo网站| 亚洲欧美日韩国产中文专区| 国产伦精品一区二区三区精品| 成人久久网站| 在线免费观看一区| aⅴ在线免费观看| 国产丝袜在线观看视频| 亚洲美女免费视频| 正在播放一区二区三区| 国产精品久久久久一区二区国产| 粉嫩嫩av羞羞动漫久久久| 成人精品视频久久久久| 日韩乱码一区二区三区| 香蕉久久国产| 91av在线免费观看| 日韩成人在线免费视频| 国产精品99一区二区| 在线中文字幕日韩| 少妇久久久久久久久久| 神马日本精品| 日韩高清人体午夜| 成人性生活免费看| 免费看久久久| 亚洲国产成人久久综合| 国产51自产区| 黄色成人美女网站| 亚洲精品美女在线观看| 精品无码国产一区二区三区51安| 国产 日韩 欧美 综合 一区| 精品久久人人做人人爰| 97中文字幕在线观看| 91成人福利| 精品国产一区二区三区av性色| 黑人无套内谢中国美女| 视频在线一区| 精品久久久三级丝袜| 国产吃瓜黑料一区二区| 成人免费在线电影网| 亚洲精品在线免费观看视频| 无码人妻精品一区二区三区99不卡| h视频久久久| 亚洲精品成人久久| 青青草视频成人| 啪啪亚洲精品| 日韩一区二区福利| 国产va在线播放| 国产日韩欧美| 国产精品91一区| 97精品人妻一区二区三区在线 | 永久免费未满蜜桃| 日日狠狠久久偷偷综合色| 亚洲美女又黄又爽在线观看| 国产视频三区四区| 亚洲精品a级片| 国内外成人免费激情在线视频网站| 日韩精品视频免费看| 丝袜亚洲另类欧美| 91精品视频观看| 免费的黄色av| 国产欧美综合在线观看第十页| 一区二区三视频| 免费不卡av| 在线观看一区二区精品视频| 香蕉视频xxxx| 窝窝社区一区二区| 最好看的2019年中文视频| 久久精品黄色片| 国产欧美69| 国产欧亚日韩视频| 秋霞视频一区二区| 国产精品丝袜在线| 日韩黄色短视频| 九九热这里有精品| 亚洲国产美女精品久久久久∴| 自拍偷拍视频亚洲| 国产一区美女| 国产美女扒开尿口久久久| 欧美一区二区在线观看视频| 国产欧美综合在线| 日韩国产欧美亚洲| 不卡精品视频| 国产性色av一区二区| 青青草精品在线视频| 视频一区视频二区中文| 成人黄色在线免费观看| 啊v视频在线| 午夜精品久久久久久久久| 狠狠操狠狠干视频| 久久av导航| 欧美精品九九久久| 国产乱淫a∨片免费视频| 久久免费电影网| cao在线观看| 成人豆花视频| 中文字幕在线国产精品| 老熟妇仑乱一区二区av| 成人综合婷婷国产精品久久免费| 亚洲欧洲日韩综合二区| 日韩电影网站| 日韩h在线观看| 激情四射综合网| 欧美aaa在线| 欧美日韩成人一区二区三区| av美女在线观看| 日韩写真欧美这视频| 久久久久麻豆v国产| 久久狠狠婷婷| 欧美福利精品| 性国裸体高清亚洲| 亚洲激情中文字幕| 久久精品国产亚洲AV无码男同 | 免费黄色在线| 欧美三级中文字幕| 91精品国自产在线| 天堂成人国产精品一区| 日本成人黄色| 欧美美女日韩| 亚洲人成77777在线观看网| 天天爽夜夜爽夜夜爽精品| 成人福利电影精品一区二区在线观看| 久久免费视频2| **精品中文字幕一区二区三区| 国产一区二区成人| 中文字幕激情视频| 国产精品久久久久永久免费观看 | 久久久成人精品| 国产精品久久免费| 亚洲婷婷国产精品电影人久久| 国产探花在线看| 亚洲精品888| 99视频日韩| 高清毛片在线观看| 日韩经典中文字幕| 狠狠狠狠狠狠狠| 日本一区二区三区高清不卡| 五月天激情视频在线观看| 成人精品亚洲| 国产欧美日韩最新| 操你啦视频在线| 精品伦理精品一区| 六月丁香激情综合| 国产欧美一区二区三区鸳鸯浴 | 不卡av免费在线| 久久五月天小说| 91久久爱成人| 国产一二在线播放| 亚洲人永久免费| 97超碰资源站| 亚洲成国产人片在线观看| 91视频啊啊啊| 久久激五月天综合精品| 超碰10000| 日韩极品少妇| 国产精品永久免费视频| 在线免费观看污| 日韩第一页在线| 在线观看免费视频一区| 亚洲精品欧美综合四区| 中文字幕在线观看网址| 老司机午夜精品| 缅甸午夜性猛交xxxx| 国产一区2区| 99久久国产免费免费| 欧美成人黑人| 欧美精品免费在线| 黄色大片在线看| 日韩欧美你懂的| 日韩综合在线观看| 一区二区在线免费| 日本性高潮视频| 国产成人免费av在线| 91av俱乐部| 欧美日本中文| 色姑娘综合av| 风间由美中文字幕在线看视频国产欧美| 国产成一区二区| 成人性生交大片免费看在线播放| 亚洲色图在线观看| 蜜桃在线一区二区| 欧美日韩精品免费观看视频| 日韩成人av毛片| 亚洲欧美色图小说| 天天干天天舔天天操| 懂色av一区二区三区蜜臀 | 视频91a欧美| 欧洲成人在线观看| 男女羞羞视频在线观看| 深夜精品寂寞黄网站在线观看| 欧美综合视频在线| 欧美一级艳片视频免费观看| 色老头在线视频| 岛国av一区二区| 久久精品人妻一区二区三区| 亚洲人成影院在线观看| 黄色片在线观看免费| 91麻豆精品在线观看| 色哟哟网站在线观看| 麻豆91精品91久久久的内涵| 国产精品-区区久久久狼| 亚洲午夜91| 精品嫩模一区二区三区| 97精品国产福利一区二区三区| 欧美精彩一区二区三区| 精品三级av| 国产精选在线观看91| 无码国模国产在线观看| 91传媒视频在线观看| 91精品福利观看| 国产精品一区二区3区| 国产a亚洲精品| 国产精品视频区| 国产成人精品一区二区三区免费 | japanese国产在线观看| 欧美性jizz18性欧美| 国产成人亚洲精品自产在线| 亚洲一本大道在线| 国产精品第二十页| 亚洲线精品一区二区三区八戒| 欧美国产精品一二三| 亚洲女人****多毛耸耸8| 萌白酱视频在线| 成人欧美一区二区三区小说| 国产又粗又硬又长又爽| 最近日韩中文字幕| 日韩成人毛片视频| 亚洲精品久久7777| 精品无码一区二区三区电影桃花 | 日日骚av一区二区| 色琪琪一区二区三区亚洲区| 免费看污视频的网站| 欧美亚洲高清一区| 91中文字幕在线视频| 欧美一级日韩一级| 亚洲国产精彩视频| 亚洲精品91美女久久久久久久| 五月婷婷六月丁香综合| 亚洲精品自拍视频| 黄色在线播放| 久久精品青青大伊人av| 日韩激情美女| 91精品国产91久久久久久| 88xx成人永久免费观看| 国产欧美日韩专区发布| 亚洲码欧美码一区二区三区| 国产麻豆日韩| 奇米狠狠一区二区三区| 亚洲欧美影院| 欧美视频四区| 国产精品免费观看久久| 美女国产一区二区三区| 天天操夜夜操很很操| av一区二区不卡| 久久久久久成人网| 亚洲免费观看高清完整版在线 | 国产丝袜在线观看视频| 国产精品99久久久久久白浆小说| 色狠狠一区二区三区| 久久精品magnetxturnbtih| 欧美激情国产在线| 国产欧美日韩小视频| 首页国产欧美日韩丝袜| 污视频在线观看免费网站| 久久午夜老司机| 国产一二三四区| 欧美视频在线看| 国产精品爽爽久久| 亚洲免费影视第一页| 国产不卡在线| 国产精品草莓在线免费观看| 精品国产亚洲一区二区三区在线| 久久99精品久久久水蜜桃| 亚洲国产精品91| av免费中文字幕| 高清在线成人网| 国产91在线播放九色| 精品久久久久久亚洲国产300| 91尤物国产福利在线观看| 日韩精品一区二区三区第95| 成人影欧美片| 国产精品免费视频xxxx| 久本草在线中文字幕亚洲| 在线免费观看一区二区三区| 嫩草成人www欧美| wwwxx日本| 亚洲欧美国产高清| 中文字幕日本视频| 日韩成人中文字幕在线观看| 性欧美猛交videos| 91精品视频免费| 日韩欧美高清在线播放| 欧美黄色免费影院| 成人av在线影院| 久久国产在线视频| 91麻豆精品91久久久久同性| 在线看的av网站| 日韩av观看网址| 琪琪久久久久日韩精品| 日本久久久网站| 国产一区二区三区黄视频| www中文在线| 欧美午夜电影在线播放| 免费一级毛片在线观看| 国产91精品高潮白浆喷水| 一区二区三区四区精品视频| 久久最新免费视频| 六月丁香婷婷久久| 国产传媒视频在线| 91福利视频在线| 国产在线一二| 国产精品99久久久久久久久| 国产精品美女久久久久久不卡| a在线视频观看| 91小视频在线免费看| 日韩黄色在线视频| 日韩电影大片中文字幕| 小视频免费在线观看| 国产精品制服诱惑| 亚洲激情av| 精品国产人妻一区二区三区| 精品免费在线观看| 三级视频在线播放| 青草热久免费精品视频| 亚洲国产欧美日韩在线观看第一区| 欧美成人高潮一二区在线看| 99久久久久久| 国产www在线| 亚洲视频在线观看| 成人国产网站| 日韩精品第1页| 成人一区二区三区中文字幕| 久久久久久久久久91| 亚洲国产天堂久久国产91 | 亚洲一区二区乱码| 一本一道久久a久久精品综合蜜臀| 免费在线超碰| 国产日韩欧美另类| 欧美精品大片| 老熟妇精品一区二区三区| 色呦呦一区二区三区| 在线免费黄色| 91精品久久久久久蜜桃| 国产欧美激情| 国产日韩精品中文字无码| 制服丝袜亚洲色图| av蜜臀在线| 四虎永久国产精品| 国产一区二区导航在线播放| 国产无精乱码一区二区三区| 亚洲毛片一区二区| 日韩三级一区| 91.com在线| 国产日韩av一区二区| 99精品在线视频观看| 羞羞色国产精品| 成人情趣视频| 手机免费看av片| 精品1区2区3区| 国内老司机av在线| 任我爽在线视频精品一| 国产精品资源站在线| 国产情侣自拍av| 日韩专区在线播放| 欧美理伦片在线播放| 蜜臀一区二区三区精品免费视频 | 欧美亚洲日本一区二区三区| 国产丝袜在线精品| 国产高清在线观看视频| 日本一本a高清免费不卡| 亚洲国产老妈| 亚洲av片不卡无码久久| 欧美一区二区黄色| 朝桐光一区二区| 人体内射精一区二区三区| 欧美国产精品中文字幕|