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

如何基于 Golang 標準庫實現插件功能

開發
插件可以在解耦的基礎上靈活擴展應用功能,本文介紹了如何基于Golang標準庫實現插件功能,幫助我們構建更靈活可擴展的應用。

什么是插件

簡單來說,插件就是可以被其他軟件加載的軟件,通常用于擴展應用程序的功能和外觀,插件的開發人員甚至可以不直接修改基礎應用程序。

你很可能在日常生活中使用過插件,也許用的是其他名稱,如擴展(extensions)或附加組件(add-ons)。最常見的例子就是 VSCode 擴展,你應該用過 VSCode,對吧?畢竟這是最受程序員歡迎的文本編輯器。如果你用過,一定會同意 VSCode 本身就是一個文本編輯器,而不是集成開發環境。其基本功能非常簡單,幾乎不支持集成開發環境中常見的功能,如調試、自動完成和測試導航等。不過,通過編輯器的擴展市場,可以找到支持這些功能以及其他更多功能的各種插件。事實上,插件已成為編輯器的主要賣點之一,促使工具開發人員集中精力為編輯器制作專用插件,有時甚至超越了編碼本身的范疇,就像 Figma 所做的那樣[2]。

對于 VSCode 而言,插件是用 JavaScript 編寫的,但也有基于 Go 編寫插件的情況。例如 Terraform(云提供商基礎設施即代碼服務),它允許用戶為其工具編寫插件[3],從而與多個云供應商(AWS、GCP、Azure......)進行交互。

另一個例子是 API 網關服務 Kong,它允許開發人員使用不同語言(包括 Go)編寫插件,這些插件[4]可以在將請求轉發給底層服務之前,對接收到的請求進行處理。

免責聲明

  • 本文假設你至少對 Go 語言有基本的了解。如果還不了解,建議先了解一下 Go[5],然后再來閱讀。
  • 本文示例代碼中的某些功能要求至少使用 Go 1.21.0 版本。
  • Windows 機器尚未支持 Go 的插件功能。如果你用的是 Windows,建議使用 WSL[6]。
  • 本文生成的代碼可在 Github 代碼庫[7]中找到。

插件的基礎設施

我們將插件基礎架構分為三個部分:協議/API、實現和插件加載器。請注意,這種劃分不是官方標準,也不是紙上談兵,而是在實際應用中的通常做法。

協議/API

協議是我們任意設置的定義和默認值,這樣就可以在各組件之間進行簡潔的通信。和任何協議一樣,需要設定插件和基礎應用程序之間的通信方式。為此,我們可以使用不同的方法,既可以通過簡單的文檔解釋期望的方法,也可以定義接口庫(編程接口,如 class foo implements bar)。只要插件的實現遵循這些準則,應用就能調用插件代碼。

實現

我們需要編碼來實現協議設定的功能。也就是說,需要在插件代碼中實現預期的函數和變量,以便主應用程序可以調用。

提醒一下,插件代碼并不局限于這些實現方式。

插件加載器

這是需要由主應用程序執行的部分,有兩個職責:查找插件并在代碼中加載其功能。

插件是主程序項目的外部組件,因此需要一種方法來查找該程序的所有插件。我們可以簡單的在文件系統中定義一個固定的文件夾來存放所有插件,但最好是允許應用程序用戶通過配置文件來指向他們的插件,或者兩種方式同時支持。

安裝所有插件后,需要在應用程序中訪問它們的應用程序接口。這通常是通過鉤子實現的:運行時調用插件(或插件的一部分)的部分。以 VSCode 為例,"文件加載時"就是這樣一個鉤子,因此插件可以使用這個鉤子捕捉加載的文件并據此運行。實現哪些鉤子以及何時實現鉤子與應用程序的邏輯有內在聯系,只能具體問題具體分析。

我們在構建什么

學習編程的最佳方式莫過于動手實踐。因此我們來創建一個使用插件的簡單應用程序。

我們要構建的是一個基于插件的 HTTP 重定向服務。這是一個簡單的 HTTP 服務,監聽端口中的請求并將其重定向到另一個服務器,同時將響應傳遞給原始客戶端。有了這項服務,我們就可以接入請求并對其進行修改。在本例中,我們將通過插件獲取請求并打印。

至于插件加載部分,我們使用Go庫作為協議,并通過配置文件來定位插件。

1.開發插件協議

我們首先定義插件協議。為此,我們定義一個 go 庫組件。

在定義該模塊之前,我們先定義應用程序組件:

# From a folder you want to keep the project:
mkdir http-redirect
cd http-redirect
go work init
go mod init github.com/<your_github_username>/http-redirect
go work use .

當然,你可以自行決定應用名稱。因為需要多個模塊進行交互,因此我們決定使用 go 工作區。要了解更多相關信息,請查看文檔[8]。

接下來可以創建庫組件了:

# From http-redirect
mkdir protocol
cd protocol
go mod init github.com/<your_github_username>/http-redirect/protocol
go work use . # Add new module to workspace

接下來創建一些文件,整個文件樹應該是這樣的:

我們將在 protocol.go 中開展工作。我們希望在協議中為每個請求調用函數。因此,我們要為插件實現一個名為 PreRequestHook 的函數,看起來是這樣的:

// protocol.go
package protocol

import "net/http"

// Plugins should export a variable called "Plugin" which implements this interface
type HttpRedirectPlugin interface {
  PreRequestHook(*http.Request)
}

代碼很簡單,我們只需獲取指向 http.Request 類型的指針(因為可能更改請求),然后將每個 HTTP 請求傳遞給我們的服務器。我們使用的是標準庫定義的類型,但請注意,也可以根據應用需求使用不同的類型。

就是這樣!但不要被例子的簡單性所迷惑。對于大型應用來說,這可能是一個相當大的文件,其中包含不同的接口、默認實現、配置和其他亂七八糟的東西。

2.實現插件

現在有了一個可遵循的協議,就可以創建并實現插件了。

同樣,我們為插件創建一個新組件,并為其創建一個文件。

# From http-redirect
mkdir log-plugin
cd log-plugin
go mod init github.com/<your_github_username>/http-redirect/log-plugin
go work use . # Add new module to workspace
touch plugin.go

現在的文件樹應該是這樣的:

我們來編寫插件!首先,創建一個函數來打印請求。

// log-plugin/plugin.go
package main

import (
  "log/slog"
  "net/http"
  "net/http/httputil"
)

func logRequest(req *http.Request) {
  result, err := httputil.DumpRequest(req, true)
  if err != nil {
    slog.Error("Failed to print request", "err", err)
  }
  slog.Info("Request sent:", "req", result)
}

func logRequestLikeCUrl(req *http.Request) {
  panic("Unimplemented!")
}

func main() { /*empty because it does nothing*/ }

這里的未實現函數只是為了顯示我們可以為更復雜的協議添加更多功能,只是目前還無法正確配置,因此不會使用。

我們要用到的是 logRequest 函數,它通過 go 標準庫的結構化日志組件打印請求。這就完成了我們的功能,但現在需要導出插件,使其滿足協議要求。

你可能注意到了,有一個什么也不做的 main 函數。這是 go 編譯器的要求,因為某些功能需要一個入口點。雖然這個編譯包中存在 main 函數,但不會作為可執行文件被調用。

我們需要導入庫。一般情況下,可以使用 go get 來恢復這個庫,但由于我們是在本地機器上開發,因此只需在 go.mod 文件中添加庫路徑即可:

replace github.com/profusion/http-redirect/protocol => ../protocol

接下來我們創建一個實現 HttpRedirectPlugin 接口的結構體,并調用日志函數。

// log-plugin/plugin.go
package main

import (
  //…
  "github.com/<your_github_username>/http-redirect/protocol"
)

// … previous code …

type PluginStr struct{}

// Compile time check for
// PreRequestHook implements protocol.HttpRedirectPlugin.
var _ protocol.HttpRedirectPlugin = PluginStr{}

// PreRequestHook implements protocol.HttpRedirectPlugin.
func (p PluginStr) PreRequestHook(req *http.Request) {
  logRequest(req)
}

var Plugin = PluginStr{}

這就是需要的所有代碼。我們只需將其作為插件構建即可。為此,我們只需向 go 編譯器傳遞 buildmode 標志:

# From http-redirect/log-plugin
go build -buildmode=plugin -o plugin.so plugin.go

瞧!我們有了一個插件!現在只需將其加載到應用程序就行了。

3.加載插件

我們需要一個應用程序來加載插件。這不是本文的重點,但以下是 Go 中 HTTP 重定向服務器代碼,我們可以對其進行修改。

// cmd/main.go
package main

import (
  "flag"
  "fmt"
  "io"
  "log/slog"
  "net/http"
  "strings"
)

var from int
var to string

func init() {
  flag.IntVar(&from, "from", 5555, "Local port to get requests")
  flag.StringVar(&to, "to", "", "Target server to redirect request to")
}

func main() {
  flag.Parse()
  Listen()
}

type proxy struct{}

func Listen() {
  p := &proxy{}
  srvr := http.Server{
    Addr: fmt.Sprintf(":%d", from),
    Handler: p,
  }
  if err := srvr.ListenAndServe(); err != nil {
    slog.Error("Server is down", "Error", err)
  }
}

// ServeHTTP implements http.Handler.
func (p *proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  // Remove original URL for redirect
  req.RequestURI = ""

  // Set URL accordingly
  req.URL.Host = to
  if req.TLS == nil {
    req.URL.Scheme = "http"
  } else {
    req.URL.Scheme = "https"
  }

  // Remove connection headers
  // (will be replaced by redirect client)
  DropHopHeaders(&req.Header)

  // Register Proxy Request
  SetProxyHeader(req)

  // Resend request
  client := &http.Client{}

  resp, err := client.Do(req)

  if err != nil {
    http.Error(rw, "Server Error: Redirect failed", http.StatusInternalServerError)
  }
  defer resp.Body.Close()

  // Once again, remove connection headers
  DropHopHeaders(&resp.Header)
  
  // Prepare and send response
  CopyHeaders(rw.Header(), &resp.Header)
  rw.WriteHeader(resp.StatusCode)
  if _, err = io.Copy(rw, resp.Body); err != nil {
    slog.Error("Error writing response", "error", err)
  }
}

func CopyHeaders(src http.Header, dst *http.Header) {
  for headingName, headingValues := range src {
    for _, value := range headingValues {
      dst.Add(headingName, value)
    }
  }
}

// Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{
  "Connection",
  "Keep-Alive",
  "Proxy-Authenticate",
  "Proxy-Authorization",
  "Te", // canonicalized version of "TE"
  "Trailers",
  "Transfer-Encoding",
  "Upgrade",
}

func DropHopHeaders(head *http.Header) {
  for _, header := range hopHeaders {
    head.Del(header)
  }
}

func SetProxyHeader(req *http.Request) {
  headerName := "X-Forwarded-for"
  target := to
  if prior, ok := req.Header[headerName]; ok {
    // Not first proxy, append
    target = strings.Join(prior, ", ") + ", " + target
  }
  req.Header.Set(headerName, target)
}

首先需要找到插件的位置。為此,我們將用 JSON 定義配置文件,在里面定義路徑列表,在本文中列表里只有一項,但請注意,這是一個為插件定義配置的機會。


// config.json
[
  "log-plugin/plugin.so"
]

這就足夠了。然后我們編寫讀取該文件內容的代碼,為了保持整潔,將在另一個文件中進行插件加載。

// cmd/plugin.go
package main

import (
  "encoding/json"
  "os"
)

// global but private, safe usage here in this file
var pluginPathList []string

func LoadConfig() {
  f, err := os.ReadFile("config.json")
  if err != nil {
    // NOTE: in real cases, deal with this error
    panic(err)
  }
  json.Unmarshal(f, &pluginPathList)
}

然后加載插件本身,為此我們將使用標準庫中的 golang 插件組件[9]。

// cmd/plugin.go
package main

import (
  //…
  "plugin"
)

// ...previous code...

var pluginList []*plugin.Plugin

func LoadPlugins() {
  // Allocate a list for storing all our plugins
  pluginList = make([]*plugin.Plugin, 0, len(pluginPathList))
  for _, p := range pluginPathList {
    // We use plugin.Open to load the plugin by path
    plg, err := plugin.Open(p)
    if err != nil {
      // NOTE: in real cases, deal with this error
      panic(err)
    }
    pluginList = append(pluginList, plg)
  }
}

// Let's throw this here so it loads the plugins as soon as we import this module
func init() {
  LoadConfig()
  LoadPlugins()
}

插件加載后,就可以訪問其符號了,包括我們在協議中定義的變量 Plugin。我們修改之前的代碼,保存這個變量,而不是整個插件?,F在,我們的文件看起來是這樣的:

// cmd/plugin.go

import (
  //…
  "protocol"
  "net/http"
)

//…

// Substitute previous code
var pluginList []*protocol.HttpRedirectPlugin

func LoadPlugins() {
  // Allocate a list for storing all our plugins
  pluginList = make([]*protocol.HttpRedirectPlugin, 0, len(pluginPathList))
  for _, p := range pluginPathList {
    // We use plugin.Open to load plugins by path
    plg, err := plugin.Open(p)
    if err != nil {
      // NOTE: in real cases, deal with this error
      panic(err)
    }
  
    // Search for variable named "Plugin"
    v, err := plg.Lookup("Plugin")
    if err != nil {
      // NOTE: in real cases, deal with this error
      panic(err)
    }
    
    // Cast symbol to protocol type
    castV, ok := v.(protocol.HttpRedirectPlugin)
    if !ok {
      // NOTE: in real cases, deal with this error
      panic("Could not cast plugin")
    }
    
    pluginList = append(pluginList, &castV)
  }
}

// …

很好,現在 pluginList 中的所有變量都是正常的 golang 變量,可以直接訪問,就好像從一開始就是代碼的一部分。然后,我們構建鉤子函數,在發送請求前調用所有插件鉤子。

// cmd/plugin.go

//…

func PreRequestHook(req *http.Request) {
  for _, plg := range pluginList {
    // Plugin is a list of pointers, we need to dereference them
    // to use the proper function
    (*plg).PreRequestHook(req)
  }
}

最后,在主代碼中調用鉤子:

// cmd/main.go

//…

// ServeHTTP implements http.Handler.
func (p *proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  PreRequestHook(req)
// …

就是這樣!我們創建了一個應用程序和一個插件,將插件加載到應用中,然后針對收到的每個請求運行插件代碼,并記錄這些請求。

想要測試?直接運行就行:

# From http-redirect
go run cmd/*.go -from <port> -to <url>

結論

我們在本文中討論了什么是插件、插件的用途,以及如何基于 Go 標準庫創建支持插件的應用程序的能力。在未來的工作中,請考慮通過這種基礎架構為解決方案提供更好的可擴展性,從而幫助其他開發人員可以更廣泛的使用我們的工具和應用。

責任編輯:趙寧寧 來源: DeepNoMind
相關推薦

2023-11-14 08:38:43

Golang人臉識別

2024-01-29 08:04:48

Golang標準庫服務端

2024-02-05 08:50:57

Golang標準庫客戶端

2020-10-22 06:59:09

GolangRust語言

2024-10-09 17:19:04

GoGolangKubernetes

2021-01-29 08:56:13

Golang標準庫函數

2010-01-22 13:31:58

C++標準庫

2019-12-09 10:03:40

MySQLSQL數據庫

2024-11-12 08:00:00

LSM樹GolangMemTable

2020-11-23 14:16:42

Golang

2010-03-26 13:39:28

Python標準庫

2021-07-28 13:03:42

Golang熔斷語言

2011-03-22 10:48:28

Nagios監控

2024-09-04 08:46:38

2009-12-08 15:06:33

WCF傳輸DataSe

2022-11-23 10:22:12

組件庫前端

2022-09-19 13:49:55

操作系統鴻蒙

2022-11-24 16:11:27

2023-07-28 09:26:43

GolangZap
點贊
收藏

51CTO技術棧公眾號

中文字幕av观看| 亚洲黄色免费av| 日韩精品91| 亚洲图区在线| 欧美日韩午夜剧场| 日本一区二区三区免费看| 日本妇乱大交xxxxx| 欧美~级网站不卡| 日韩精品欧美国产精品忘忧草 | 毛毛毛毛毛毛毛片123| free性欧美| 欧美高清一级片在线观看| 4444kk亚洲人成电影在线| 91在线视频在线观看| 亚洲人metart人体| 国产精品一区二区免费在线观看| 日本在线小视频| 免费看成人哺乳视频网站| 欧美日韩国产bt| 欧美一区二区视频在线播放| 男人的天堂在线视频| 亚洲不卡中文字幕| 中文字幕无码日韩专区免费| 超碰97久久国产精品牛牛| 色婷婷久久久亚洲一区二区三区 | 中韩乱幕日产无线码一区| 粉嫩13p一区二区三区| 日本一本a高清免费不卡| tube国产麻豆| 欧美日中文字幕| 亚洲精品国产精品国产自| 国产美女视频免费看| 精品91久久| 精品国产乱码久久久久久婷婷 | 亚洲性色视频| 日韩在线观看成人| 51妺嘿嘿午夜福利| 色天下一区二区三区| 精品国产乱码久久久久久影片| 亚洲免费999| 亚洲天堂1区| 色婷婷久久久亚洲一区二区三区| 欧美成人免费在线观看视频| 污污的网站在线看| 日韩久久一区二区| 一本一道久久a久久精品综合| 青青青手机在线视频观看| 成人av电影在线| 高清国产在线一区| 亚洲国产福利视频| 国产精品1区二区.| 亚洲精品欧美极品| 国产绿帽一区二区三区| 蜜芽一区二区三区| 国产精品一区电影| 中文字幕 自拍偷拍| 蜜臀av性久久久久蜜臀av麻豆| 国产999视频| 欧美一区二区三区不卡视频| 1024精品一区二区三区| 国内精品久久久久影院优| 久久久久香蕉视频| 黄色免费成人| 国模私拍视频一区| 国产一级av毛片| 亚洲精品乱码| 国产成人黄色av| 自拍偷拍精品视频| 狠狠色2019综合网| 97伦理在线四区| 高清毛片aaaaaaaaa片| k8久久久一区二区三区| 国产在线资源一区| 日本aaa在线观看| 日本一区免费视频| 一道本在线观看视频| 怡红院在线播放| 午夜精品免费在线观看| 无码精品国产一区二区三区免费| 日韩福利一区| 欧美精品三级在线观看| 日本少妇xxxx软件| 日本欧美高清| 中文字幕精品一区二区精品| 日韩欧美视频免费观看| 欧美日韩精品免费观看视频完整| 国模吧一区二区三区| 日日夜夜狠狠操| 狠狠色丁香婷婷综合久久片| 国产伦精品一区二区三区视频黑人| 色欲av伊人久久大香线蕉影院| 久久综合色8888| 中文字幕一区二区三区有限公司 | 日本黄色三级视频| 久久久精品2019中文字幕之3| 亚洲v国产v| 性欧美ⅴideo另类hd| 欧美性猛交xxxx黑人| 岛国av免费在线| 国偷自产av一区二区三区| 在线观看视频亚洲| 青青草激情视频| 男人的天堂成人在线| 91免费人成网站在线观看18| 西西人体44www大胆无码| 最新热久久免费视频| 国产中文字幕视频在线观看| 亚洲国产一区二区久久| 日韩精品黄色网| 黄色一级片中国| 视频在线观看国产精品| 国产成人精品福利一区二区三区 | 国产精品色在线| 亚洲熟妇av日韩熟妇在线| 日本成人在线网站| 亚洲欧美色婷婷| 久久精品女人毛片国产| 久久国产尿小便嘘嘘| 免费影院在线观看一区| 日本在线观看大片免费视频| 欧美日韩综合不卡| 最新中文字幕视频| 亚洲精品九九| 古典武侠综合av第一页| 高h视频在线观看| 精品视频在线免费看| 丰满少妇一区二区三区| 激情婷婷欧美| 99中文字幕| 哥也色在线视频| 欧美日韩国产在线观看| www.狠狠爱| 国产精品久久777777毛茸茸| 国产高清自拍一区| 青春草视频在线| 欧美精品免费视频| 国产精品20p| 性欧美暴力猛交另类hd| 精品久久久久亚洲| a国产在线视频| 精品国产免费人成电影在线观看四季 | 婷婷精品在线| 欧美在线观看日本一区| 人妻中文字幕一区| 午夜精品福利久久久| 超碰caoprom| 亚洲毛片一区| 精品国产一区二区三区四区精华 | 岛国一区二区三区| 一本一本a久久| 国产一区精品福利| 色吧影院999| 国产又粗又猛又黄又爽无遮挡 | 91aaa在线观看| 国产精品99久久久久久宅男| 最新视频 - x88av| 成人在线视频区| 欧美高清在线播放| 天天综合网在线| 欧美小视频在线| 色一情一交一乱一区二区三区| 老牛国产精品一区的观看方式| 久久av免费观看| 成人美女大片| 国产一区二区动漫| 亚洲一区二区视频在线播放| 中文字幕一区二区三区av| 亚洲一区二区中文字幕在线观看| 欧美在线亚洲| 韩日午夜在线资源一区二区| 国产精欧美一区二区三区蓝颜男同| 亚洲人成伊人成综合网久久久| 国产黄色免费视频| 亚洲欧洲三级电影| 日本一区二区在线观看视频| 久久不射2019中文字幕| 亚洲视频欧美在线| 日韩成人在线观看视频| 97超级碰碰人国产在线观看| 青青草在线免费视频| 91成人在线精品| 亚洲人与黑人屁股眼交| 国产成人av一区二区三区在线 | 久久人妻无码aⅴ毛片a片app| 国产麻豆视频一区| 日韩久久一级片| 91精品福利| 精品一区二区三区国产| 欧美一级做a| 91国在线精品国内播放| 全色精品综合影院| 日韩午夜三级在线| 国产精品一区无码| 中文字幕一区在线观看视频| 在线观看成人动漫| 久久精品国产亚洲aⅴ | 2018av在线| 亚洲片国产一区一级在线观看| 中文字幕天堂在线| 国产精品久久久久久久久免费丝袜| 亚洲精品鲁一鲁一区二区三区 | 水蜜桃久久夜色精品一区| 不卡日韩av| 成人激情综合| 欧美风情在线观看| 婷婷在线视频| 国产偷亚洲偷欧美偷精品| 国产三级伦理片| 欧美性猛交xxxx富婆弯腰| 久热这里有精品| 国产欧美日韩在线观看| 久久国产劲爆∧v内射| 男女性色大片免费观看一区二区| 国产午夜精品久久久久久久久| 亚洲视频一二三四| 久久免费大视频| 精品欧美日韩| 少妇精品在线| 91精品久久久久久久久中文字幕 | 久久久久久久久久av| 99精品老司机免费视频| 日韩av在线资源| www.国产黄色| 7777精品伊人久久久大香线蕉经典版下载 | 波多野结衣成人在线| 欧美激情啪啪| 国产精品久久91| 成人欧美大片| 91av网站在线播放| 99re6在线精品视频免费播放| 美日韩精品视频免费看| 午夜免费福利在线观看| 国产亚洲精品一区二区| 瑟瑟在线观看| 日韩电视剧在线观看免费网站| 亚洲第九十九页| 欧美一区二区三区日韩视频| 91精品国产乱码久久久| 欧美在线观看你懂的| 久久精品视频7| 大荫蒂欧美视频另类xxxx| 欧美成人手机视频| 亚洲精品少妇30p| 日本妇女毛茸茸| 亚洲精品视频在线观看网站| 免费看特级毛片| 中文字幕一区av| 人人澡人人澡人人看| 日韩理论片在线| 欧美三级免费看| 亚洲综合色噜噜狠狠| 久久久久久久久久久97| 亚洲综合久久久久| 国产一级二级三级| 亚洲超丰满肉感bbw| 91香蕉在线视频| 色婷婷亚洲婷婷| 怡春院在线视频| 欧美一区二区三区思思人| 国产不卡精品视频| 精品日韩在线观看| 欧美 中文字幕| 精品视频偷偷看在线观看| 女人偷人在线视频| 搡老女人一区二区三区视频tv| 黄色免费网站在线观看| 欧美日韩成人精品| av日韩中文| 国产精品久久久久久久久免费 | 亚洲精品一区二区三区在线播放| 亚洲色图在线播放| 国产无遮挡又黄又爽在线观看| 午夜视频久久久久久| 秋霞精品一区二区三区| 欧美久久久久久久久中文字幕| 精品国产乱码一区二区三| 亚洲国产高清自拍| 欧美日韩在线中文字幕| 中文字幕亚洲图片| 蜜桃传媒在线观看免费进入 | 四虎精品永久免费| 翡翠波斯猫1977年美国| 国产九一精品| 欧美中文字幕在线观看视频| 香蕉亚洲视频| 亚洲黄色片免费| 91在线你懂得| 亚洲色图27p| 亚洲成av人片在线| 依依成人在线视频| 日韩av在线网| 久操视频在线观看| 91精品国产精品| 日本亚洲欧洲无免费码在线| 国产在线资源一区| 91精品国偷自产在线电影| 国产v片免费观看| 久久国产欧美日韩精品| 欧美熟妇精品黑人巨大一二三区| 中文字幕在线不卡视频| 日韩免费av片| 宅男在线国产精品| 加勒比一区二区三区在线| 美女精品视频一区| 99欧美精品| 久久精品人人做人人爽电影| 中文字幕一区二区三三| 黄色一级二级三级| 成人a免费在线看| 51精品免费网站| 在线观看视频91| 完全免费av在线播放| 91精品国产成人| av自拍一区| 大桥未久一区二区三区| 日韩av在线发布| 短视频在线观看| 亚洲一区二区五区| 国产又粗又大又爽| 视频在线观看99| 国模一区二区| 快播亚洲色图| 日韩视频精品在线观看| 日本一区二区免费视频| 亚洲精品国产品国语在线app| 在线观看不卡的av| 国产亚洲精品日韩| 国产v综合v| 欧美精品在线一区| 亚洲一区久久| 人妻av一区二区| 亚洲国产精品一区二区久久恐怖片| 国产欧美久久久精品免费| 日韩一中文字幕| 开心久久婷婷综合中文字幕 | 中文字幕av亚洲精品一部二部| 五月婷婷丁香色| 国产精品久久久久久亚洲伦| 伊人网综合在线| 久久精品国产欧美激情| 四虎国产精品免费久久| 三年中国中文在线观看免费播放| 麻豆精品久久久| 战狼4完整免费观看在线播放版| 欧美性猛交xxxxxxxx| 草草影院在线观看| 国产精品视频久久久| 日韩精品免费一区二区在线观看| 日韩av播放器| 欧美高清在线视频| 91禁在线观看| 久久99久久99精品免观看粉嫩| 香蕉成人app| 国产高清av在线播放| 成人国产在线观看| 天天爽夜夜爽夜夜爽精品| 日韩麻豆第一页| 麻豆精品蜜桃| 伊人久久婷婷色综合98网| 国内精品自线一区二区三区视频| 欧美成人一二三区| 亚洲国产精品久久久久久| 日本黄色免费在线| 日韩欧美三级电影| 国内精品视频一区二区三区八戒| 青春草免费在线视频| 韩剧1988免费观看全集| 激情av综合| 欧美牲交a欧美牲交aⅴ免费真 | 先锋影音av在线| 欧美高清视频不卡网| 美女网站视频在线| 麻豆精品蜜桃一区二区三区| 青青草国产精品亚洲专区无| 黄色a级片在线观看| 精品国产麻豆免费人成网站| 神马电影网我不卡| 一本一生久久a久久精品综合蜜| 国产成人免费网站| 天堂网av手机版| 日韩在线观看网站| 久久夜色电影| 天天干天天综合| 在线观看亚洲免费视频| 一区二区三区欧美在线观看| 人妻无码中文字幕免费视频蜜桃| 日本韩国欧美精品大片卡二| 欧美aaaa视频| 国产a级黄色片| 精品视频在线视频| 成年网站在线视频网站| 免费在线观看91| 成人小说亚洲一区二区三区 | 黄色网址视频在线观看| 99在线影院| 日韩午夜一区| 国外成人免费视频| baoyu135国产精品免费| 日本黄网站免费| 中文字幕一区二|