日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
使用gorilla/mux進(jìn)行HTTP請(qǐng)求路由和驗(yàn)證

gorilla/mux 包以直觀的 API 提供了 HTTP 請(qǐng)求路由、驗(yàn)證和其它服務(wù)。

蘆山網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,蘆山網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為蘆山1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的蘆山做網(wǎng)站的公司定做!

Go 網(wǎng)絡(luò)庫包括 http.ServeMux 結(jié)構(gòu)類型,它支持 HTTP 請(qǐng)求多路復(fù)用(路由):Web 服務(wù)器將托管資源的 HTTP 請(qǐng)求與諸如 /sales4today 之類的 URI 路由到代碼處理程序;處理程序在發(fā)送 HTTP 響應(yīng)(通常是 HTML 頁面)之前執(zhí)行適當(dāng)?shù)倪壿嫛?這是該體系的草圖:

 
 
 
 
  1.              +-----------+     +--------+     +---------+
  2. HTTP 請(qǐng)求---->| web 服務(wù)器 |---->| 路由 |---->| 處理程序 |
  3.              +-----------+     +--------+     +---------+

調(diào)用 ListenAndServe 方法后啟動(dòng) HTTP 服務(wù)器:

 
 
 
 
  1. http.ListenAndServe(":8888", nil) // args: port & router

第二個(gè)參數(shù) nil 意味著 DefaultServeMux 用于請(qǐng)求路由。

gorilla/mux 庫包含 mux.Router 類型,可替代 DefaultServeMux 或自定義請(qǐng)求多路復(fù)用器。 在 ListenAndServe 調(diào)用中,mux.Router 實(shí)例將代替 nil 作為第二個(gè)參數(shù)。 下面的示例代碼很好的說明了為什么 mux.Router如此吸引人:

1、一個(gè)簡(jiǎn)單的 CRUD web 應(yīng)用程序

crud web 應(yīng)用程序(見下文)支持四種 CRUD(創(chuàng)建/讀取/更新/刪除)操作,它們分別對(duì)應(yīng)四種 HTTP 請(qǐng)求方法:POST、GET、PUT 和 DELETE。 在這個(gè) CRUD 應(yīng)用程序中,所管理的資源是套話與反套話的列表,每個(gè)都是套話及其反面的的套話,例如這對(duì):

 
 
 
 
  1. Out of sight, out of mind. Absence makes the heart grow fonder.

可以添加新的套話對(duì),可以編輯或刪除現(xiàn)有的套話對(duì)。

CRUD web 應(yīng)用程序:

 
 
 
 
  1. package main
  2. import (
  3. "gorilla/mux"
  4. "net/http"
  5. "fmt"
  6. "strconv"
  7. )
  8. const GETALL string = "GETALL"
  9. const GETONE string = "GETONE"
  10. const POST string = "POST"
  11. const PUT string = "PUT"
  12. const DELETE string = "DELETE"
  13. type clichePair struct {
  14. Id int
  15. Cliche string
  16. Counter string
  17. }
  18. // Message sent to goroutine that accesses the requested resource.
  19. type crudRequest struct {
  20. verb string
  21. cp *clichePair
  22. id int
  23. cliche string
  24. counter string
  25. confirm chan string
  26. }
  27. var clichesList = []*clichePair{}
  28. var masterId = 1
  29. var crudRequests chan *crudRequest
  30. // GET /
  31. // GET /cliches
  32. func ClichesAll(res http.ResponseWriter, req *http.Request) {
  33. cr := &crudRequest{verb: GETALL, confirm: make(chan string)}
  34. completeRequest(cr, res, "read all")
  35. }
  36. // GET /cliches/id
  37. func ClichesOne(res http.ResponseWriter, req *http.Request) {
  38. id := getIdFromRequest(req)
  39. cr := &crudRequest{verb: GETONE, id: id, confirm: make(chan string)}
  40. completeRequest(cr, res, "read one")
  41. }
  42. // POST /cliches
  43. func ClichesCreate(res http.ResponseWriter, req *http.Request) {
  44. cliche, counter := getDataFromRequest(req)
  45. cp := new(clichePair)
  46. cp.Cliche = cliche
  47. cp.Counter = counter
  48. cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
  49. completeRequest(cr, res, "create")
  50. }
  51. // PUT /cliches/id
  52. func ClichesEdit(res http.ResponseWriter, req *http.Request) {
  53. id := getIdFromRequest(req)
  54. cliche, counter := getDataFromRequest(req)
  55. cr := &crudRequest{verb: PUT, id: id, cliche: cliche, counter: counter, confirm: make(chan string)}
  56. completeRequest(cr, res, "edit")
  57. }
  58. // DELETE /cliches/id
  59. func ClichesDelete(res http.ResponseWriter, req *http.Request) {
  60. id := getIdFromRequest(req)
  61. cr := &crudRequest{verb: DELETE, id: id, confirm: make(chan string)}
  62. completeRequest(cr, res, "delete")
  63. }
  64. func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
  65. crudRequests<-cr
  66. msg := <-cr.confirm
  67. res.Write([]byte(msg))
  68. logIt(logMsg)
  69. }
  70. func main() {
  71. populateClichesList()
  72. // From now on, this gorountine alone accesses the clichesList.
  73. crudRequests = make(chan *crudRequest, 8)
  74. go func() { // resource manager
  75. for {
  76. select {
  77. case req := <-crudRequests:
  78. if req.verb == GETALL {
  79. req.confirm<-readAll()
  80. } else if req.verb == GETONE {
  81. req.confirm<-readOne(req.id)
  82. } else if req.verb == POST {
  83. req.confirm<-addPair(req.cp)
  84. } else if req.verb == PUT {
  85. req.confirm<-editPair(req.id, req.cliche, req.counter)
  86. } else if req.verb == DELETE {
  87. req.confirm<-deletePair(req.id)
  88. }
  89. }
  90. }()
  91. startServer()
  92. }
  93. func startServer() {
  94. router := mux.NewRouter()
  95. // Dispatch map for CRUD operations.
  96. router.HandleFunc("/", ClichesAll).Methods("GET")
  97. router.HandleFunc("/cliches", ClichesAll).Methods("GET")
  98. router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
  99. router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
  100. router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
  101. router.HandleFunc("/cliches/{id:[0-9]+}", ClichesDelete).Methods("DELETE")
  102. http.Handle("/", router) // enable the router
  103. // Start the server.
  104. port := ":8888"
  105. fmt.Println("\nListening on port " + port)
  106. http.ListenAndServe(port, router); // mux.Router now in play
  107. }
  108. // Return entire list to requester.
  109. func readAll() string {
  110. msg := "\n"
  111. for _, cliche := range clichesList {
  112. next := strconv.Itoa(cliche.Id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
  113. msg += next
  114. }
  115. return msg
  116. }
  117. // Return specified clichePair to requester.
  118. func readOne(id int) string {
  119. msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
  120. index := findCliche(id)
  121. if index >= 0 {
  122. cliche := clichesList[index]
  123. msg = "\n" + strconv.Itoa(id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
  124. }
  125. return msg
  126. }
  127. // Create a new clichePair and add to list
  128. func addPair(cp *clichePair) string {
  129. cp.Id = masterId
  130. masterId++
  131. clichesList = append(clichesList, cp)
  132. return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
  133. }
  134. // Edit an existing clichePair
  135. func editPair(id int, cliche string, counter string) string {
  136. msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
  137. index := findCliche(id)
  138. if index >= 0 {
  139. clichesList[index].Cliche = cliche
  140. clichesList[index].Counter = counter
  141. msg = "\nCliche edited: " + cliche + " " + counter + "\n"
  142. }
  143. return msg
  144. }
  145. // Delete a clichePair
  146. func deletePair(id int) string {
  147. idStr := strconv.Itoa(id)
  148. msg := "\n" + "Bad Id: " + idStr + "\n"
  149. index := findCliche(id)
  150. if index >= 0 {
  151. clichesList = append(clichesList[:index], clichesList[index + 1:]...)
  152. msg = "\nCliche " + idStr + " deleted\n"
  153. }
  154. return msg
  155. }
  156. //*** utility functions
  157. func findCliche(id int) int {
  158. for i := 0; i < len(clichesList); i++ {
  159. if id == clichesList[i].Id {
  160. return i;
  161. }
  162. }
  163. return -1 // not found
  164. }
  165. func getIdFromRequest(req *http.Request) int {
  166. vars := mux.Vars(req)
  167. id, _ := strconv.Atoi(vars["id"])
  168. return id
  169. }
  170. func getDataFromRequest(req *http.Request) (string, string) {
  171. // Extract the user-provided data for the new clichePair
  172. req.ParseForm()
  173. form := req.Form
  174. cliche := form["cliche"][0] // 1st and only member of a list
  175. counter := form["counter"][0] // ditto
  176. return cliche, counter
  177. }
  178. func logIt(msg string) {
  179. fmt.Println(msg)
  180. }
  181. func populateClichesList() {
  182. var cliches = []string {
  183. "Out of sight, out of mind.",
  184. "A penny saved is a penny earned.",
  185. "He who hesitates is lost.",
  186. }
  187. var counterCliches = []string {
  188. "Absence makes the heart grow fonder.",
  189. "Penny-wise and dollar-foolish.",
  190. "Look before you leap.",
  191. }
  192. for i := 0; i < len(cliches); i++ {
  193. cp := new(clichePair)
  194. cp.Id = masterId
  195. masterId++
  196. cp.Cliche = cliches[i]
  197. cp.Counter = counterCliches[i]
  198. clichesList = append(clichesList, cp)
  199. }
  200. }

為了專注于請(qǐng)求路由和驗(yàn)證,CRUD 應(yīng)用程序不使用 HTML 頁面作為請(qǐng)求響應(yīng)。 相反,請(qǐng)求會(huì)產(chǎn)生明文響應(yīng)消息:套話對(duì)的列表是對(duì) GET 請(qǐng)求的響應(yīng),確認(rèn)新的套話對(duì)已添加到列表中是對(duì) POST 請(qǐng)求的響應(yīng),依此類推。 這種簡(jiǎn)化使得使用命令行實(shí)用程序(如 curl)可以輕松地測(cè)試應(yīng)用程序,尤其是 gorilla/mux 組件。

gorilla/mux 包可以從 GitHub 安裝。 CRUD app ***期運(yùn)行;因此,應(yīng)使用 Control-C 或同等命令終止。 CRUD 應(yīng)用程序的代碼,以及自述文件和簡(jiǎn)單的 curl 測(cè)試,可以在我的網(wǎng)站上找到。

2、請(qǐng)求路由

mux.Router 擴(kuò)展了 REST 風(fēng)格的路由,它賦給 HTTP 方法(例如,GET)和 URL 末尾的 URI 或路徑(例如 /cliches)相同的權(quán)重。 URI 用作 HTTP 動(dòng)詞(方法)的名詞。 例如,在HTTP請(qǐng)求中有一個(gè)起始行,例如:

 
 
 
 
  1. GET /cliches

意味著得到所有的套話對(duì),而一個(gè)起始線,如:

 
 
 
 
  1. POST /cliches

意味著從 HTTP 正文中的數(shù)據(jù)創(chuàng)建一個(gè)套話對(duì)。

在 CRUD web 應(yīng)用程序中,有五個(gè)函數(shù)充當(dāng) HTTP 請(qǐng)求的五種變體的請(qǐng)求處理程序:

 
 
 
 
  1. ClichesAll(...)    # GET: 獲取所有的套話對(duì)
  2. ClichesOne(...)    # GET: 獲取指定的套話對(duì)
  3. ClichesCreate(...) # POST: 創(chuàng)建新的套話對(duì)
  4. ClichesEdit(...)   # PUT: 編輯現(xiàn)有的套話對(duì)
  5. ClichesDelete(...) # DELETE: 刪除指定的套話對(duì)

每個(gè)函數(shù)都有兩個(gè)參數(shù):一個(gè) http.ResponseWriter 用于向請(qǐng)求者發(fā)送一個(gè)響應(yīng),一個(gè)指向 http.Request 的指針,該指針封裝了底層 HTTP 請(qǐng)求的信息。 使用 gorilla/mux 包可以輕松地將這些請(qǐng)求處理程序注冊(cè)到Web服務(wù)器,并執(zhí)行基于正則表達(dá)式的驗(yàn)證。

CRUD 應(yīng)用程序中的 startServer 函數(shù)注冊(cè)請(qǐng)求處理程序。 考慮這對(duì)注冊(cè),router 作為 mux.Router 實(shí)例:

 
 
 
 
  1. router.HandleFunc("/", ClichesAll).Methods("GET")
  2. router.HandleFunc("/cliches", ClichesAll).Methods("GET")

這些語句意味著對(duì)單斜線 //cliches 的 GET 請(qǐng)求應(yīng)該路由到 ClichesAll 函數(shù),然后處理請(qǐng)求。 例如,curl 請(qǐng)求(使用 作為命令行提示符):

 
 
 
 
  1. % curl --request GET localhost:8888/

會(huì)產(chǎn)生如下結(jié)果:

 
 
 
 
  1. 1: Out of sight, out of mind.  Absence makes the heart grow fonder.
  2. 2: A penny saved is a penny earned.  Penny-wise and dollar-foolish.
  3. 3: He who hesitates is lost.  Look before you leap.

這三個(gè)套話對(duì)是 CRUD 應(yīng)用程序中的初始數(shù)據(jù)。

在這句注冊(cè)語句中:

 
 
 
 
  1. router.HandleFunc("/cliches", ClichesAll).Methods("GET")
  2. router.HandleFunc("/cliches", ClichesCreate).Methods("POST")

URI 是相同的(/cliches),但動(dòng)詞不同:***種情況下為 GET 請(qǐng)求,第二種情況下為 POST 請(qǐng)求。 此注冊(cè)舉例說明了 REST 樣式的路由,因?yàn)閮H動(dòng)詞的不同就足以將請(qǐng)求分派給兩個(gè)不同的處理程序。

注冊(cè)中允許多個(gè) HTTP 方法,盡管這會(huì)影響 REST 風(fēng)格路由的精髓:

 
 
 
 
  1. router.HandleFunc("/cliches", DoItAll).Methods("POST", "GET")

除了動(dòng)詞和 URI 之外,還可以在功能上路由 HTTP 請(qǐng)求。 例如,注冊(cè)

 
 
 
 
  1. router.HandleFunc("/cliches", ClichesCreate).Schemes("https").Methods("POST")

要求對(duì) POST 請(qǐng)求進(jìn)行 HTTPS 訪問以創(chuàng)建新的套話對(duì)。以類似的方式,注冊(cè)可能需要具有指定的 HTTP 頭元素(例如,認(rèn)證憑證)的請(qǐng)求。

3、 Request validation

gorilla/mux 包采用簡(jiǎn)單,直觀的方法通過正則表達(dá)式進(jìn)行請(qǐng)求驗(yàn)證。 考慮此請(qǐng)求處理程序以獲取一個(gè)操作:

 
 
 
 
  1. router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")

此注冊(cè)排除了 HTTP 請(qǐng)求,例如:

 
 
 
 
  1. % curl --request GET localhost:8888/cliches/foo

因?yàn)?foo 不是十進(jìn)制數(shù)字。該請(qǐng)求導(dǎo)致熟悉的 404(未找到)狀態(tài)碼。 在此處理程序注冊(cè)中包含正則表達(dá)式模式可確保僅在請(qǐng)求 URI 以十進(jìn)制整數(shù)值結(jié)束時(shí)才調(diào)用 ClichesOne 函數(shù)來處理請(qǐng)求:

 
 
 
 
  1. % curl --request GET localhost:8888/cliches/3  # ok

另一個(gè)例子,請(qǐng)求如下:

 
 
 
 
  1. % curl --request PUT --data "..." localhost:8888/cliches

此請(qǐng)求導(dǎo)致狀態(tài)代碼為 405(錯(cuò)誤方法),因?yàn)?/cliches URI 在 CRUD 應(yīng)用程序中僅在 GET 和 POST 請(qǐng)求中注冊(cè)。 像 GET 請(qǐng)求一樣,PUT 請(qǐng)求必須在 URI 的末尾包含一個(gè)數(shù)字 id:

 
 
 
 
  1. router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")

4、并發(fā)問題

gorilla/mux 路由器作為單獨(dú)的 Go 協(xié)程執(zhí)行對(duì)已注冊(cè)的請(qǐng)求處理程序的每次調(diào)用,這意味著并發(fā)性被內(nèi)置于包中。 例如,如果有十個(gè)同時(shí)發(fā)出的請(qǐng)求,例如

 
 
 
 
  1. % curl --request POST --data "..." localhost:8888/cliches

然后 mux.Router 啟動(dòng)十個(gè) Go 協(xié)程來執(zhí)行 ClichesCreate 處理程序。

GET all、GET one、POST、PUT 和 DELETE 中的五個(gè)請(qǐng)求操作中,***三個(gè)改變了所請(qǐng)求的資源,即包含套話對(duì)的共享 clichesList。 因此,CRUD app 需要通過協(xié)調(diào)對(duì) clichesList 的訪問來保證安全的并發(fā)性。 在不同但等效的術(shù)語中,CRUD app 必須防止 clichesList 上的競(jìng)爭(zhēng)條件。 在生產(chǎn)環(huán)境中,可以使用數(shù)據(jù)庫系統(tǒng)來存儲(chǔ)諸如 clichesList 之類的資源,然后可以通過數(shù)據(jù)庫事務(wù)來管理安全并發(fā)。

CRUD 應(yīng)用程序采用推薦的Go方法來實(shí)現(xiàn)安全并發(fā):

  • 只有一個(gè) Go 協(xié)程,資源管理器在 CRUD app startServer 函數(shù)中啟動(dòng),一旦 Web 服務(wù)器開始偵聽請(qǐng)求,就可以訪問 clichesList。
  • 諸如 ClichesCreateClichesAll 之類的請(qǐng)求處理程序向 Go 通道發(fā)送(指向)crudRequest 實(shí)例(默認(rèn)情況下是線程安全的),并且資源管理器單獨(dú)從該通道讀取。 然后,資源管理器對(duì) clichesList 執(zhí)行請(qǐng)求的操作。

安全并發(fā)體系結(jié)構(gòu)繪制如下:

 
 
 
 
  1.            crudRequest                讀/寫
  2. 請(qǐng)求處理程序 -------------> 資源托管者 ------------> 套話列表

在這種架構(gòu)中,不需要顯式鎖定 clichesList,因?yàn)橐坏?CRUD 請(qǐng)求開始進(jìn)入,只有一個(gè) Go 協(xié)程(資源管理器)訪問 clichesList。

為了使 CRUD 應(yīng)用程序盡可能保持并發(fā),在一方請(qǐng)求處理程序與另一方的單一資源管理器之間進(jìn)行有效的分工至關(guān)重要。 在這里,為了審查,是 ClichesCreate 請(qǐng)求處理程序:

 
 
 
 
  1. func ClichesCreate(res http.ResponseWriter, req *http.Request) {
  2. cliche, counter := getDataFromRequest(req)
  3. cp := new(clichePair)
  4. cp.Cliche = cliche
  5. cp.Counter = counter
  6. cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
  7. completeRequest(cr, res, "create")
  8. }

ClichesCreate 調(diào)用實(shí)用函數(shù) getDataFromRequest,它從 POST 請(qǐng)求中提取新的套話和反套話。 然后 ClichesCreate 函數(shù)創(chuàng)建一個(gè)新的 ClichePair,設(shè)置兩個(gè)字段,并創(chuàng)建一個(gè) crudRequest 發(fā)送給單個(gè)資源管理器。 此請(qǐng)求包括一個(gè)確認(rèn)通道,資源管理器使用該通道將信息返回給請(qǐng)求處理程序。 所有設(shè)置工作都可以在不涉及資源管理器的情況下完成,因?yàn)樯形丛L問 clichesList

請(qǐng)求處理程序調(diào)用實(shí)用程序函數(shù),該函數(shù)從 POST 請(qǐng)求中提取新的套話和反套話。 然后,該函數(shù)創(chuàng)建一個(gè)新的,設(shè)置兩個(gè)字段,并創(chuàng)建一個(gè) crudRequest 發(fā)送到單個(gè)資源管理器。 此請(qǐng)求包括一個(gè)確認(rèn)通道,資源管理器使用該通道將信息返回給請(qǐng)求處理程序。 所有設(shè)置工作都可以在不涉及資源管理器的情況下完成,因?yàn)樯形丛L問它。

completeRequest 實(shí)用程序函數(shù)在 ClichesCreate 函數(shù)和其他請(qǐng)求處理程序的末尾調(diào)用:

 
 
 
 
  1. completeRequest(cr, res, "create") // shown above

通過將 crudRequest 放入 crudRequests 頻道,使資源管理器發(fā)揮作用:

 
 
 
 
  1. func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
  2.    crudRequests<-cr          // 向資源托管者發(fā)送請(qǐng)求
  3.    msg := <-cr.confirm       // 等待確認(rèn)
  4.    res.Write([]byte(msg))    // 向請(qǐng)求方發(fā)送確認(rèn)
  5.    logIt(logMsg)             // 打印到標(biāo)準(zhǔn)輸出
  6. }

對(duì)于 POST 請(qǐng)求,資源管理器調(diào)用實(shí)用程序函數(shù) addPair,它會(huì)更改 clichesList 資源:

 
 
 
 
  1. func addPair(cp *clichePair) string {
  2.    cp.Id = masterId  // 分配一個(gè)唯一的 ID
  3.    masterId++        // 更新 ID 計(jì)數(shù)器
  4.    clichesList = append(clichesList, cp) // 更新列表
  5.    return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
  6. }

資源管理器為其他 CRUD 操作調(diào)用類似的實(shí)用程序函數(shù)。 值得重復(fù)的是,一旦 Web 服務(wù)器開始接受請(qǐng)求,資源管理器就是唯一可以讀取或?qū)懭?clichesList 的 goroutine。

對(duì)于任何類型的 Web 應(yīng)用程序,gorilla/mux 包在簡(jiǎn)單直觀的 API 中提供請(qǐng)求路由、請(qǐng)求驗(yàn)證和相關(guān)服務(wù)。 CRUD web 應(yīng)用程序突出了軟件包的主要功能。


新聞名稱:使用gorilla/mux進(jìn)行HTTP請(qǐng)求路由和驗(yàn)證
轉(zhuǎn)載來于:http://www.dlmjj.cn/article/dpsspos.html