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

beego API開發以及自動化文檔

開發 前端 開發工具 自動化
beego1.3版本已經在上個星期發布了,但是還是有很多人不了解如何來進行開發,也是在一步一步的測試中開發,期間QQ群里面很多人都問我如何開發,我的業余時間實在是排的太滿了,實在是沒辦法一一回復大家,在這里和大家說聲對不起,這兩天我又不斷的改進,寫了一個應用示例展示如何使用beego開發API已經自動化文檔和測試,這里就和大家詳細的解說一下。

beego API開發以及自動化文檔

beego1.3版本已經在上個星期發布了,但是還是有很多人不了解如何來進行開發,也是在一步一步的測試中開發,期間QQ群里面很多人都問我如何開發,我的業余時間實在是排的太滿了,實在是沒辦法一一回復大家,在這里和大家說聲對不起,這兩天我又不斷的改進,寫了一個應用示例展示如何使用beego開發API已經自動化文檔和測試,這里就和大家詳細的解說一下。

自動化文檔開發的初衷

我們需要開發一個API應用,然后需要和手機組的開發人員一起合作,當然我們首先想到的是文檔先行,我們也根據之前的經驗寫了我們需要的API原型文檔,我們還是根據github的文檔格式寫了一些漂亮的文檔,但是我們開始擔心這個文檔如果兩邊不同步怎么辦?因為畢竟是原型文檔,變動是必不可少的。手機組有一個同事之前在雅虎工作過,他推薦我看一個swagger的應用,看了swagger的標準和文檔化的要求,感覺太棒了,這個簡直就是神器啊,通過swagger可以方便的查看API的文檔,同時使用API的用戶可以直接通過swagger進行請求和獲取結果。所以我就開始學習swagger的標準,同時開始進行Go源碼的研究,通過Go里面的AST進行源碼分析,針對comments解析,然后生成swagger標準的json格式,這樣最后就可以和swagger完美結合了。

這樣做的好處有三個:

  1. 注釋標準化

  2. 有了注釋之后,以后API代碼維護相當方便

  3. 根據注釋自動化生成文檔,方便調用的用戶查看和測試

beego API應用入門

請大家更新到最新的bee和beego

go get -u github.com/beego/bee
go get -u github.com/astaxie/beego

然后進入到你的GOPATH/src目錄,執行命令bee api bapi,進入目錄cd bapi,執行命令bee run -downdoc=true -docgen=true.請看下面我執行的效果圖:

執行完成之后就打開瀏覽器,輸入URL:http://127.0.0.1:8080/swagger/swagger-1/

記住這里必須要用127.0.0.1,不能使用localhost,存在CORS問題,Ajax跨域

我們的效果和應用都出來了,很酷很炫吧,那這后面到底采用了怎么樣的一些技術呢?讓我們一步一步來講解這些細節:

項目目錄

我們首先來了解一下bee api創建的應用的目錄結構:

|-- bapi
|-- conf
|   `-- app.conf
|-- controllers
|   |-- object.go
|   `-- user.go
|-- docs
|   |-- doc.go
|   `-- docs.go
|-- lastupdate.tmp
|-- main.go
|-- models
|   |-- object.go
|   `-- user.go
|-- routers
|   |-- commentsRouter.go
|   `-- router.go
|-- swagger
`-- tests
    `-- default_test.go
  • main.go 是程序的統一入口文件

  • bapi 是生成的二進制文件

  • conf 配置文件目錄,app.conf

  • controllers 控制器目錄,主要是邏輯的處理

  • models 是數據處理層的目錄

  • docs 是自動化生成文檔的目錄

  • lastupdate.tmp 是一個注解路由的緩存文件

  • routers是路由目錄,主要涉及一些路由規則

  • swagger 是一個html靜態資源目錄,是通過bee自動下載的,主要就是展示我們看到的界面及測試

  • test 目錄是針對應用的測試用例,beego相比其他revel框架的好處之一就是無需啟動應用就可以執行test case。

#p#

入口文件main

我們第一步先來看一下入口是怎么寫的?

 

  1. package main  
  2.  
  3. import (  
  4.     _ "bapi/docs" 
  5.     _ "bapi/routers" 
  6.  
  7.     "github.com/astaxie/beego" 
  8. )  
  9.  
  10. func main() {  
  11.     if beego.RunMode == "dev" {  
  12.         beego.DirectoryIndex = true 
  13.         beego.StaticDir["/swagger"] = "swagger" 
  14.     }  
  15.     beego.Run()  

 

入口文件就是一個普通的beego應用的標準代碼,只是這里多了幾行代碼,把swagger加入了static,因為我們需要把文檔服務器集成到beego的API應用中來。然后增加了docs的初始化引入,和router的效果一樣。接下里我們先來看看自動化API的路由是怎么設計的

namespace路由

自動化路由才有了namespace來進行設計,而且注意兩點,第一目前只支持namespace的路由支持自動化文檔,第二只支持NSNamespace和NSInclude解析,而且是只能兩個層級,先看我們的路由設置:

 

  1. func init() {  
  2.     ns := beego.NewNamespace("/v1",  
  3.         beego.NSNamespace("/object",  
  4.             beego.NSInclude(  
  5.                 &controllers.ObjectController{},  
  6.             ),  
  7.         ),  
  8.         beego.NSNamespace("/user",  
  9.             beego.NSInclude(  
  10.                 &controllers.UserController{},  
  11.             ),  
  12.         ),  
  13.     )  
  14.     beego.AddNamespace(ns)  

 

我們先來看一下這個代碼,首先是使用beego.NewNamespace創建一個ns的變量,這個變量里面其實就是存儲了一棵路由樹,我們可以把這棵樹加到其他任意已經存在的樹中去,這也就是namespace的好處,可以在任意的模塊中設計自己的namespace,然后把這個namespace加到其他的應用中去,可以增加任意的前綴等。

這里我們分析一下NewNamespace這個函數,這個函數的定義是這樣的NewNamespace(prefix string, params ...innnerNamespace) *Namespace,他的第一個參數就是前綴,第二個參數是innnerNamespace多參數,那么我們來看看innnerNamespace的定義是什么:

 

  1. type innnerNamespace func(*Namespace) 

 

它是一個函數,也就是只要是符合參數是*Namespace的函數都可以。那么在beego里面定義了如下的方法支持返回這個函數類型:

  • NSCond(cond namespaceCond) innnerNamespace

  • NSBefore(filiterList ...FilterFunc) innnerNamespace

  • NSAfter(filiterList ...FilterFunc) innnerNamespace

  • NSInclude(cList …ControllerInterface) innnerNamespace

  • NSRouter(rootpath string, c ControllerInterface, mappingMethods …string) innnerNamespace

  • NSGet(rootpath string, f FilterFunc) innnerNamespace

  • NSPost(rootpath string, f FilterFunc) innnerNamespace

  • NSDelete(rootpath string, f FilterFunc) innnerNamespace

  • NSPut(rootpath string, f FilterFunc) innnerNamespace

  • NSHead(rootpath string, f FilterFunc) innnerNamespace

  • NSOptions(rootpath string, f FilterFunc) innnerNamespace

  • NSPatch(rootpath string, f FilterFunc) innnerNamespace

  • NSAny(rootpath string, f FilterFunc) innnerNamespace

  • NSHandler(rootpath string, h http.Handler) innnerNamespace

  • NSAutoRouter(c ControllerInterface) innnerNamespace

  • NSAutoPrefix(prefix string, c ControllerInterface) innnerNamespace

  • NSNamespace(prefix string, params …innnerNamespace) innnerNamespace

因此我們可以在NewNamespace這個函數的第二個參數列表中使用上面的任意函數作為參數調用。

我們看一下路由代碼,這是一個層級嵌套的函數,第一個參數是/v1,即為/v1開頭的路由樹,第二個參數是beego.NSNamespace,第三個參數也是beego.NSNamespace,也就是路由樹嵌套了路由樹,而我們的beego.NSNamespace里面也是和NewNamespace一樣的參數,第一個參數是路由前綴,第二個參數是slice參數。這里我們調用了beego.NSInclude來進行注解路由的引入,這個函數是專門為注解路由設計的,我們可以看到這個設計里面我們沒有任何的路由信息,只是設置了前綴,那么這個的路由是在哪里設置的呢?我們接下來分析什么是注解路由。

注解路由

可能有些同學不了解什么是注解路由,也就是在Controller類上添加一個注釋讓框架給自動添加Route,那么我們來看一下ObjectControllerUserController中怎么寫路由注解的:

 

  1. // Operations about object  
  2. type ObjectController struct {  
  3.     beego.Controller  
  4. }  
  5.  
  6. // @Title create  
  7. // @Description create object  
  8. // @Param   body        body    models.Object   true        "The object content"  
  9. // @Success 200 {string} models.Object.Id  
  10. // @Failure 403 body is empty  
  11. // @router / [post]  
  12. func (this *ObjectController) Post() {  
  13.     var ob models.Object  
  14.     json.Unmarshal(this.Ctx.Input.RequestBody, &ob)  
  15.     objectid := models.AddOne(ob)  
  16.     this.Data["json"] = map[string]string{"ObjectId": objectid}  
  17.     this.ServeJson()  

 

我們看到我們的每一個函數上面有大段的注釋,注解路由其實主要關注最后一行// @router / [post],這一行的注釋就是表示這個函數是注冊到路由/,支持方法是post

和我們平常的時候使用beego.Router("/", &ObjectController{},"post:Post")的效果是一模一樣的,只是這一次框架幫你自動注冊了這樣的路由,框架是如何來自動注冊的呢?在應用啟動的時候,會判斷是否有調用NSInclude,在調用的時候,判斷RunMode是否是dev模式,是的話就會判斷是否之前有分析過,并且分析對象目錄有更新,就使用Go的AST進行源碼分析(當然只分析NSInclude調用的controller),然后生成文件routers/commentsRouter.go,在該文件中會自動注冊我們需要的路由信息。這樣就完成了整個的注解路由注冊。

注解路由是使用// @router 開頭來申明的,而且必須放在你要注冊的函數的上方,和其他注釋@Title @Description的順序無關,你可以放在第一行,也可以最后一行。有兩個參數,第一個是需要注冊的路由,第二個是支持的方法。

路由可以支持beego支持的任意規則,例如/object/:key這樣的參數路由,也可以固定路由/object,也可以是正則路由/cms_:id([0-9]+).html

支持的HTTP方法必須使用[]中間是支持的方法列表,多個使用,分割,例如[post,get]。但是目前自動化文檔只支持一個方法,也就是你多個的方法的時候無法做到RESTFul到同一個函數,也不鼓勵你這樣設計的API。如果你API設計的時候支持了多個方法,那么文檔生成的時候默認是取第一個作為支持的方法。

上面我們看到我們的方法上面有很多注釋,那么接下來就進入我們今天的重點:自動化文檔

自動化文檔

所謂的自動化文檔,說白了就是根據我們的注釋自動的生成我們可以看得懂的漂亮文檔。我們上面也說了寫注釋不僅僅是方便我們的代碼維護,邏輯闡述,同時如果能夠自動生成文檔,那么對于使用API的用戶來說也是很大的幫助。那么如何進行自動化文檔生成呢?

我當初看了swagger的展示效果之后,首先研究了他的spec,發現是一些json數據,只要我們的API能夠生成swagger認識的json就可以了,因此我的思路就來了,根據注釋生成swagger的JSON標準數據輸出。swagger提供了一個例子代碼:petstore 我就是根據這個例子的格式一步一步實現了現在的自動化文檔。

#p#

首先第一步就是API的描述:

API文檔

我們看到在router.go里面頭部有一大段的注釋,這些注釋就是描述整個項目的一些信息:

 

  1. // @APIVersion 1.0.0  
  2. // @Title beego Test API  
  3. // @Description beego has a very cool tools to autogenerate documents for your API  
  4. // @Contact astaxie@gmail.com  
  5. // @TermsOfServiceUrl http://beego.me/  
  6. // @License Apache 2.0  
  7. // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 

 

這里面主要是幾個標志:

  • @APIVersion

  • @Title

  • @Description

  • @Contact

  • @TermsOfServiceUrl

  • @License

  • @LicenseUrl

這里每一個都不是必須的,你可以寫也可以不寫,后面就是一個字符串,你可以使用任意喜歡的字符進行描述。我們來看一下生成的:http://127.0.0.1:8080/docs

  1. {  
  2.   "apiVersion""1.0.0",  
  3.   "swaggerVersion""1.2",  
  4.   "apis": [  
  5.     {  
  6.       "path""/object",  
  7.       "description""Operations about object\n" 
  8.     },  
  9.     {  
  10.       "path""/user",  
  11.       "description""Operations about Users\n" 
  12.     }  
  13.   ],  
  14.   "info": {  
  15.     "title""beego Test API",  
  16.     "description""beego has a very cool tools to autogenerate documents for your API",  
  17.     "contact""astaxie@gmail.com",  
  18.     "termsOfServiceUrl""http://beego.me/",  
  19.     "license""Url http://www.apache.org/licenses/LICENSE-2.0.html" 
  20.   }  

 

 

這是首次請求的一些信息,那么apis是怎么來的呢?這個就是根據你的namespace進行源碼AST分析獲取的,所以目前只支持兩層的namespace嵌套,而且必須是兩層,第一層是baseurl,第二層就是嵌套的namespace的prefix。也就是上面的path信息,那么里面的description那里獲取的呢?請看控制器的注釋,

控制器注釋文檔

針對每一個控制我們可以增加注釋,用來描述該控制器的作用:

 

  1. // Operations about object  
  2. type ObjectController struct {  
  3.     beego.Controller  

 

這個注釋就是用來表示我們的每一個控制器API的作用,而控制器的函數里面的注釋就是用來表示調用的路由、參數、作用以及返回的信息。

 

  1. // @Title Get  
  2. // @Description find object by objectid  
  3. // @Param   objectId        path    string  true        "the objectid you want to get"  
  4. // @Success 200 {object} models.Object  
  5. // @Failure 403 :objectId is empty  
  6. // @router /:objectId [get]  
  7. func (this *ObjectController) Get() {  

 

從上面的注釋我們可以把我們的注釋分為以下類別:

  • @Title

    接口的標題,用來標示唯一性,唯一,可選

    格式:之后跟一個描述字符串

  • @Description

    接口的作用,用來描述接口的用途,唯一,可選

    格式:之后跟一個描述字符串

  • @Param

    請求的參數,用來描述接受的參數,多個,可選

    格式:變量名 傳輸類型 類型 是否必須 描述

    傳輸類型:

    類型:

    變量名和描述是一個字符串

    是否必須:true 或者false

    • string

    • int

    • int64

    • 對象,這個地方大家寫的時候需要注意,需要是相對于當前項目的路徑.對象,例如models.Object表示models目錄下的Object對象,這樣bee在生成文檔的時候會去掃描改對象并顯示給用戶改對象。

    • query 表示帶在url串里面?aa=bb&cc=dd

    • form 表示使用表單遞交數據

    • path 表示URL串中得字符,例如/user/{uid} 那么uid就是一個path類型的參數

    • body 表示使用raw body進行數據的傳輸

    • header 表示通過header進行數據的傳輸

  • @Success

    成功返回的code和對象或者信息

    格式:code 對象類型 信息或者對象路徑

    code:表示HTTP的標準status code,200 201等

    對象類型:{object}表示對象,其他默認都認為是字符類型,會顯示第三個參數給用戶,如果是{object}類型,那么就會去掃描改對象,并顯示給用戶

    對象路徑和上面Param中得對象類型一樣,使用路徑.對象的方式來描述

  • @Failure

    錯誤返回的信息,

    格式: code 信息

    code:同上Success

    錯誤信息:字符串描述信息

  • @router

    上面已經描述過支持兩個參數,第一個是路由,第二個表示支持的HTTP方法

那么我們通過上面的注釋會生成怎么樣的JSON信息呢?

 

  1. {  
  2.   "path""/object/{objectId}",  
  3.   "description""",  
  4.   "operations": [  
  5.     {  
  6.       "httpMethod""GET",  
  7.       "nickname""Get",  
  8.       "type""",  
  9.       "summary""find object by objectid",  
  10.       "parameters": [  
  11.         {  
  12.           "paramType""path",  
  13.           "name""objectId",  
  14.           "description""\"the objectid you want to get\"",  
  15.           "dataType""string",  
  16.           "type""",  
  17.           "format""",  
  18.           "allowMultiple"false,  
  19.           "required"true,  
  20.           "minimum"0,  
  21.           "maximum"0 
  22.         }  
  23.       ],  
  24.       "responseMessages": [  
  25.         {  
  26.           "code"200,  
  27.           "message""models.Object",  
  28.           "responseModel""Object" 
  29.         },  
  30.         {  
  31.           "code"403,  
  32.           "message"":objectId is empty",  
  33.           "responseModel""" 
  34.         }  
  35.       ]  
  36.     }  
  37.   ]  

上面闡述的這些描述都是可以使用一個或者多個 '\t', '\n', '\v', '\f', '\r', ' ', U+0085 (NEL), U+00A0 (NBSP)進行分割

#p#

對象自定義注釋

我們的對象定義如下:

 

  1. type Object struct {  
  2.     ObjectId   string  
  3.     Score      int64  
  4.     PlayerName string  

 

通過掃描生成的代碼如下:

 

  1. Object {  
  2. ObjectId (string, optional): ,  
  3. PlayerName (string, optional): ,  
  4. Score (int64, optional):  

 

我們發現字段都是optional的,而且沒有任何針對字段的描述,其實我們可以在對象定義里面增加如下的tag:

 

  1. type Object struct {  
  2.     ObjectId   string   `required:"true" description:"object id"`  
  3.     Score      int64        `required:"true" description:"players's scores"`  
  4.     PlayerName string   `required:"true" description:"plaers name, used in system"`  

 

而且如果你的對象tag里面如果存在json或者thrift描述,那么就會使用改描述作為字段名,即如下的代碼:

 

  1. type Object struct {  
  2.     ObjectId   string   `json:"object_id"`  
  3.     Score      int64        `json:"player_score"`  
  4.     PlayerName string   `json:"player_name"`  

 

就會輸出如下的文檔信息:

 

  1. Object {  
  2. object_id (string, optional): ,  
  3. player_score (string, optional): ,  
  4. player_name (int64, optional):  

常見錯誤及問題

  1. Q:bee沒有上面執行的命令?

    A:請更新bee到最新版本,目前bee的版本是1.1.2,beego的版本是1.3.1

  2. Q:bee更新的時候出錯了?

    A:第一可能是GFW的問題,第二可能是你修改過了源碼,刪除重新下載,第三可能你升級了Go版本,你需要刪除GOPATH/pkg下的所有文件

  3. Q:下載swagger很慢?

    A:想辦法讓他變快,因為我現在放在了github上面

  4. Q:文檔生成了,但是我沒辦法測試請求?

    A:你看看你訪問的地址是不是和請求的URL是同一個地址,因為swagger是使用Ajax請求數據的,所以跨域的問題,解決CORS的辦法就是保持域一致,包括URL和端口。

  5. Q:運行的時候發生了未知的錯誤?

    A:那就來提issue或者給我留言吧,我會盡力幫助你解決你遇到的問題

原文出自:http://my.oschina.net/astaxie/blog/284072

責任編輯:林師授 來源: oschina博客
相關推薦

2014-02-17 15:15:56

ARIS文檔

2009-09-04 13:55:04

C#文檔自動化

2024-04-30 08:00:00

人工智能自動化文件處理

2017-12-17 21:58:18

2023-07-12 15:41:18

2021-04-01 13:25:46

Node命令工具

2020-01-16 09:00:00

AI人工智能ML

2021-10-14 06:52:47

自動化開發環境

2013-05-02 13:02:59

開發環境自動化團隊

2021-11-23 12:11:59

PowershellLinuxDevOps

2013-09-03 09:58:51

Web前端

2018-07-13 06:46:35

數據中心自動化微服務

2009-10-09 17:50:59

VB Script開發

2009-07-22 14:50:50

ibmdwWeb2.0Twitter

2018-02-25 19:29:49

自動化數字化IT

2020-04-29 11:28:54

智能自動化機器人流程自動化AI

2021-10-13 10:06:49

自動化IT安全

2010-12-06 09:59:58

2022-02-04 21:50:37

網絡安全自動化

2012-09-04 10:20:31

IBMdw
點贊
收藏

51CTO技術棧公眾號

欧美在线导航| 午夜老司机在线观看| 红桃视频亚洲| 亚洲精品资源美女情侣酒店| 天天插天天操天天射| 黄色精品在线观看| 99热国产精品| 国产精品爽爽ⅴa在线观看| 婷婷在线精品视频| 亚洲精品国产动漫| 欧美一区二区三区在线看| 精品少妇人妻av免费久久洗澡| 国产专区在线| 成人午夜在线播放| 国产欧美日韩91| www日韩精品| 91精品综合久久久久久久久久久| 亚洲电影免费观看高清完整版在线| 激情综合网俺也去| h片在线观看| 国产精品国产三级国产三级人妇| 99久久精品免费看国产一区二区三区| 久久久久久久久久成人| 欧美91福利在线观看| 亚洲欧美精品一区二区| 极品人妻一区二区| 国产亚洲欧美日韩精品一区二区三区| 无码av中文一区二区三区桃花岛| 亚洲欧美日本国产有色| 欧美老女人性开放| 成人免费的视频| 成人国产精品av| 久久国产乱子伦精品| 亚洲一级影院| 欧美成人免费网| 日本黄色激情视频| 亚洲综合福利| 日韩精品免费在线| 无码国产精品一区二区免费式直播| 韩国理伦片久久电影网| 一本久久精品一区二区| www..com日韩| 国产蜜臀av在线播放| 亚洲欧美日韩国产中文在线| 亚洲精品视频一二三| 久草在线免费福利资源| 91麻豆swag| 久久99九九| 五月婷婷丁香花| 成人黄色国产精品网站大全在线免费观看 | 午夜av中文字幕| 国产精品xxx| 色婷婷国产精品综合在线观看| 欧美激情 国产精品| 波多野在线观看| 一区二区三区欧美| 免费cad大片在线观看| av网站在线看| 一区二区高清视频在线观看| 丰满人妻一区二区三区53号| 伊人在我在线看导航| 综合久久一区二区三区| 亚洲第一综合网站| 超碰在线最新| 亚洲一区免费观看| www.国产在线播放| 9999在线视频| 欧美丝袜一区二区| 欧美一级黄色影院| 欧美特黄色片| 国产在线日韩欧美| 日本在线啊啊| 国产精品一级视频| 欧洲乱码伦视频免费| 国产亚洲精品久久久| 一级特黄曰皮片视频| 欧美日韩精品在线一区| 亚洲一级片在线观看| 国产区精品视频| 国产精品一区二区三区在线免费观看 | 欧美电影免费看| 91久久精品网| 亚洲黄色av片| 精品嫩草影院| 国产一区二区欧美日韩| 精品无码一区二区三区蜜臀| 亚洲手机视频| 国产精品91久久久久久| 97人妻精品一区二区三区| 国产mv日韩mv欧美| 久久综合一区| 九义人在线观看完整免费版电视剧| 亚洲男同性恋视频| 黄色成人在线看| 丁香婷婷久久| 精品国产伦一区二区三区观看方式| 亚洲熟妇无码av| 91精品亚洲| 欧美性在线观看| 91亚洲国产成人精品一区| 处破女av一区二区| 日韩国产美国| sis001亚洲原创区| 欧美性色aⅴ视频一区日韩精品| 在线免费看污网站| 亚洲女娇小黑人粗硬| 久久亚洲私人国产精品va| 久草视频在线观| 国产一区二区视频在线播放| 玛丽玛丽电影原版免费观看1977| 麻豆网在线观看| 欧美日韩中国免费专区在线看| 亚洲18在线看污www麻豆 | 偷拍自拍在线看| 91精品欧美福利在线观看| 国产精品第七页| 欧美国产先锋| 国产精品美女主播| 五月婷婷伊人网| 亚洲精品v日韩精品| 一本久道中文无码字幕av| 草草视频在线一区二区| 色吧影院999| 一本一道无码中文字幕精品热| 国产精品一二三四区| 欧美精品v国产精品v日韩精品| 国产制服丝袜一区| 久久精品国产亚洲夜色av网站| 国产精品成人国产| 欧美一卡二卡| 日本大臀精品| 国产精品无码粉嫩小泬| 日韩久久久久久久久| 一区二区三区 日韩| 欧美日韩在线资源| 黑人欧美xxxx| 亚洲视频 中文字幕| 婷婷另类小说| 国产精品视频免费在线| 久草在线免费福利资源| 疯狂做受xxxx欧美肥白少妇| 国内自拍偷拍视频| 欧美一区精品| 亚洲综合日韩在线| 国产区在线观看| 欧美片网站yy| 99热99这里只有精品| 轻轻草成人在线| 日韩欧美电影一区二区| 第四色男人最爱上成人网| 亚洲美女免费精品视频在线观看| 国产成人亚洲精品自产在线 | 精品成av人一区二区三区| 国产69久久精品成人| 天天av天天翘| 精品久久久精品| 草草影院第一页| 欧美亚洲专区| 日韩精品久久久毛片一区二区| 都市激情亚洲一区| 亚洲欧美日韩精品久久亚洲区| 亚洲av中文无码乱人伦在线视色| 久久精品视频网| 少妇黄色一级片| 色综合天天综合网中文字幕| 成人免费网站在线| av片在线观看网站| 欧美v日韩v国产v| 国产香蕉视频在线| 久久精品亚洲精品国产欧美 | 欧美videos粗暴| 日韩专区在线观看| 国产高清免费在线观看| 亚洲国产婷婷综合在线精品| 日本一区二区在线免费观看| 先锋影音国产一区| 亚洲一区三区在线观看| 欧美黄色一级| 9.1国产丝袜在线观看| 久久这里精品| 欧美精品粉嫩高潮一区二区| 久久免费视频精品| 久久综合九色综合97婷婷| 午夜免费精品视频| 亚洲影视一区| 鲁片一区二区三区| 亚洲青青一区| 97精品视频在线播放| 成人资源www网在线最新版| 91精品国产综合久久香蕉麻豆| 国产真实夫妇交换视频| 国产亚洲污的网站| 9191在线视频| 日韩精品一二区| 天天想你在线观看完整版电影免费| www.成人网| 日韩美女在线观看一区| 中文字幕在线播放网址| 国产午夜精品理论片a级探花| 伊人免费在线观看| 亚洲动漫第一页| 波多野结衣欲乱| 99re亚洲国产精品| 午夜av中文字幕| 日韩精品91亚洲二区在线观看 | 一区二区三区高清视频在线观看| 亚洲欧洲免费无码| 极品一区美女高清| 成人观看高清在线观看免费| 国产精品迅雷| 久久久视频免费观看| 色多多视频在线观看| 亚洲精品按摩视频| 国产免费视频一区二区三区| 在线亚洲人成电影网站色www| 久久综合亚洲色hezyo国产| 国产精品毛片久久久久久 | 国产蜜臀av在线一区二区三区| 免费人成视频在线播放| 日本亚洲最大的色成网站www| 免费观看国产精品视频| 欧美精品二区| 色乱码一区二区三区熟女| 国产精品亚洲人成在99www| 国产成人精品自拍| 美国十次综合久久| 91精品免费久久久久久久久| 欧美一级大片| 欧美一级黑人aaaaaaa做受| 色老头在线观看| 久久中文字幕视频| 欧美一区二区三区| 尤物tv国产一区| 国产免费a∨片在线观看不卡| 亚洲精品www久久久| 日本韩国在线观看| 欧美成人伊人久久综合网| 国产精品久久久久精| 欧美性受xxxx黑人xyx| 日本丰满少妇做爰爽爽| 日本高清成人免费播放| 成人公开免费视频| 一本色道久久综合亚洲91| 国产免费观看av| 狠狠干狠狠久久| 在线观看国产亚洲| 欧美日韩一区二区三区| 91美女免费看| 粉嫩av一区二区三区免费野| 天天综合天天干| 狠狠做深爱婷婷久久综合一区| 久久国产黄色片| 福利二区91精品bt7086| 无码人妻丰满熟妇精品| 在线视频一区二区免费| 影音先锋黄色网址| 欧美日本国产一区| 99久久精品日本一区二区免费| 91精品国产品国语在线不卡| 精品国产九九九| 欧美刺激脚交jootjob| 少妇一级淫片免费看| 亚洲精品美女在线| 欧美女同网站| 日韩天堂在线视频| a篇片在线观看网站| 欧美黑人性视频| 草草在线观看| 国产成人激情视频| 成人免费在线观看视频| 成人午夜激情网| 成人在线视频你懂的| 久久综合一区二区三区| 日韩激情免费| 免费高清一区二区三区| 国产免费成人| 精品日韩久久久| 国产在线不卡一区| 欧美xxxxx精品| 国产清纯美女被跳蛋高潮一区二区久久w | 无码无遮挡又大又爽又黄的视频| 日本一区中文字幕| 精品国产乱码久久久久久1区二区| 懂色中文一区二区在线播放| 黄色正能量网站| 综合分类小说区另类春色亚洲小说欧美 | 黑人巨大精品欧美一区免费视频 | 男人添女荫道口喷水视频| 欧美喷水视频| 欧洲av无码放荡人妇网站| 麻豆91在线观看| 精品国产乱码久久久久夜深人妻| 91丨九色丨蝌蚪丨老版| 狂野欧美性猛交| 亚洲一区二区精品3399| 动漫av在线免费观看| 97人妻精品一区二区三区动漫| 国产福利一区二区| 一起草在线视频| 中文字幕一区在线| 国产精品免费av一区二区| 在线免费不卡电影| 亚洲黄色a级片| 国产亚洲欧美aaaa| 青青草原av在线| 国产精品久久久久久久久免费看| 亚洲国产一区二区三区网站| 欧美日本一道本在线视频| 日韩乱码人妻无码中文字幕| 精品视频色一区| 天天综合永久入口| 久久精品视频中文字幕| 亚洲一区资源| 国产精品区一区| 欧美大黑bbbbbbbbb在线| 免费无遮挡无码永久视频| 国产综合色产在线精品| 男人天堂av电影| 性做久久久久久久久| 国产视频在线免费观看| 在线观看久久久久久| 九九色在线视频| 国产日韩精品电影| 国产一区二区三区电影在线观看| 日韩精品在线视频免费观看| 狠狠狠色丁香婷婷综合激情| 国产精成人品免费观看| 精品久久久久久久久久久| 亚洲成人第一区| 美乳少妇欧美精品| 欧美在线一级| 性欧美精品一区二区三区在线播放| 免费在线欧美黄色| wwwxxx色| 亚洲综合一区二区三区| 国产乱码精品一区二区| 日韩在线视频免费观看高清中文| 不卡福利视频| 久久久久久欧美精品色一二三四| 一区在线免费| 成人区人妻精品一区二| 亚洲午夜一区二区三区| 亚洲国产精品久久久久久6q| 欧美老少做受xxxx高潮| 日韩激情综合| 日韩精品手机在线观看| 国产伦精品一区二区三区视频青涩| 国产3级在线观看| 欧美精品第1页| av香蕉成人| 5g国产欧美日韩视频| 欧美精品网站| 国产伦精品一区二区三区88av| 亚洲线精品一区二区三区 | 视频一区国产视频| 国产交换配乱淫视频免费| 色婷婷av久久久久久久| 国产毛片av在线| 国产精品极品尤物在线观看| 精品少妇av| 看看黄色一级片| 亚洲蜜臀av乱码久久精品蜜桃| 国产av无码专区亚洲av| 欧美黑人国产人伦爽爽爽| 国产精品极品| 91传媒久久久| 国产精品无圣光一区二区| 一级α片免费看刺激高潮视频| 久久精品国产一区二区电影| 色播一区二区| 一女被多男玩喷潮视频| 国产婷婷一区二区| 这里只有精品6| 欧美日韩福利视频| 欧美jizz19性欧美| 久久精品视频91| 亚洲欧美一区二区三区久本道91 | 99re这里只有精品在线| 深夜精品寂寞黄网站在线观看| 国产人与zoxxxx另类91| 777av视频| 中文子幕无线码一区tr| 精品人妻一区二区三区含羞草 | 国产一区二区动漫| 国产999精品在线观看| 亚洲人成无码网站久久99热国产 | 老司机av福利| 91免费国产视频网站| 一级片在线观看视频| 欧美激情综合色| 精品免费av| 中文字幕1区2区| 欧美性高清videossexo| 欧美寡妇性猛交xxx免费| 欧美日韩在线观看一区| 国产精品一区二区在线看| 免费的毛片视频| 欧美激情videos| 日韩成人激情| 星空大象在线观看免费播放|