在 K8S 的 APIServer 的程式碼中,依賴了一個叫做 go-restful 的庫來構建 HTTP 的 API。 在學習 K8S 的程式碼過程中,我們要對這個庫做些瞭解,這樣才能更加方便地知道 APIServer 的 Restful 服務是如何構建的。
這個專案在 Github 上面的地址是:
https://github.com/emicklei/go-restful 。
我們也很容易地找到了作者的一篇介紹使用方法的部落格。
帖子的地址在:
http://ernestmicklei.com/2012/11/go-restful-first-working-example/
這裡我們將它簡單翻譯一下,幫助大家學習。下麵的內容是譯文。
在前面的一個帖子裡面,我介紹了用 Google 的 Go 語言開發的,用來構建 REST 風格 WebService 的包 go-restful 的設計。 今天,我完成了這個包的實現,包含如下的功能:
-
使用 Route 來建立 WebService,Route 是 HTTP Request 到 Go 函式的對映。
-
每個 Route 都需要的資訊包括 HTTP 請求方法(GET,POST,…),URL 路徑(/users),MimeType以及其系結的處理函式。
-
處理函式的輸入包括一個 Request 和一個 Response。
-
Request 物件用來獲取 Path 和 Query引數,Headers以及 Request Body(XML,JSON,…)。
-
Response 物件用來設定 Status,Headers,以及 Response Body
-
Request 和 Response 物件都可以使用標準庫來在物件和XML或JSON之間進行轉換。
我們可以使用一個簡單的例子來演示上面的過程。一個用來對User 物件進行 CRUD 操作的 WebService。 我們首先在一個 userservice 目錄裡面建立一個 userservice.go 檔案。
package userserviceimport ( "github.com/emicklei/go-restful"
"log")type User struct {
Id, Name string}
User 型別代表我們要操作的物件。
檔案中的下一個部分就是 WebService 的 API 定義。這些 API 是一組Route物件的集合,這些Route定義瞭如何將進來的 HTTP 請求對映到對應的處理函式。
func New() *restful.WebService { service := new(restful.WebService)
service. Path("/users"). Consumes(restful.MIME_XML, restful.MIME_JSON). Produces(restful.MIME_XML, restful.MIME_JSON)
service.Route(service.GET("/{user-id}").To(FindUser))
service.Route(service.POST("").To(UpdateUser))
service.Route(service.PUT("/{user-id}").To(CreateUser))
service.Route(service.DELETE("/{user-id}").To(RemoveUser))
return service
}
首先,使用一個 root URL 來初始化所有路徑的 service,定義每個 Route 可以接收的MIME型別,以及可以響應的MIME型別。當然這個也可以針對每個Route單獨指定。然後,service 指定它可以提供哪些路徑。這裡的函式呼叫GET("/{user-id}")
是 Method("GET").Path("/{user-id}")
的簡單寫法,這個方法呼叫建立一個 RouteBuilder 物件。然後使用這個 RouteBuilder 物件指定對應的處理函式。
下麵,就是定義每個 Route 的處理函式了。
func FindUser(request *restful.Request, response *restful.Response) { id := request.PathParameter("user-id")
// here you would fetch user from some persistence system
usr := &User;{Id: id, Name: "John Doe"} response.WriteEntity(usr)
}
Route 的處理函式的方法宣告都一樣,包含一個 Restful 的 Request 和 Response,兩個一對。 Request 是 http Request 物件的封裝,提供了一些方便的方法。Response 是對 http ResponseWriter 的封裝。這種設計方式可以將底層的 HTTP 結構開放給開發者,同時也為開發者提供了一些通用的 Restful 函式,例如 WriteEntity。WriteEntity 函式會檢查請求的 Accept 頭部來決定 response 的 Content-Type 頭部,同時也決定了使用那種方法來序列化物件(這裡就是 User 物件)。
userservice.go 檔案的其他內容就是剩下的Route處理函式的定義。
func UpdateUser(request *restful.Request, response *restful.Response) {
usr := new(User)
err := request.ReadEntity(&usr;)
if err == nil {
response.WriteEntity(usr)
} else {
response.WriteError(http.StatusInternalServerError,err)
}
}func CreateUser(request *restful.Request, response *restful.Response) {
usr := User{Id: request.PathParameter("user-id")}
err := request.ReadEntity(&usr;)
if err == nil {
response.WriteEntity(usr)
} else {
response.WriteError(http.StatusInternalServerError,err)
}
}func RemoveUser(request *restful.Request, response *restful.Response) { }
現在,我們已經完成了 UserService 的定義和實現。下麵的程式碼段演示瞭如何在一個應用中使用這個 service。
package mainimport ( "github.com/emicklei/go-restful"
"log"
"net/http"
"userservice")func main() {
restful.Add(userservice.New())
log.Fatal(http.ListenAndServe(":8080", nil))
}
服務啟動之後,我們可以利用下麵的方法測試:
-
預設的請求
$ curl http://localhost:8080/users/12xml version="1.0" encoding="UTF-8"?>
<User>
<Id>12Id>
<Name>John DoeName>
User>
-
帶 Accpet 頭部的請求
$ curl http:{ "Id": "12", "Name": "John Doe"}
-
新建一個User物件
$ curl http://localhost:9090/users -X POST -d '{"Id":"32","Name":"jemygraw"}' -H 'Content-Type: application/json'xml version="1.0" encoding="UTF-8"?>
<User>
<Id>32Id>
<Name>jemygrawName>
User>
-
新的一個User物件,要求傳回JSON。
$ curl http://localhost:9090/users -X POST -d '{"Id":"32","Name":"jemygraw"}' -H 'Content-Type: application/json' -H 'Accept: application/json'{ "Id": "32", "Name": "jemygraw"}
譯者:
本文永久儲存地址為:
https://github.com/jemygraw/TechDoc/blob/master/Go%E5%BA%93%E5%AD%A6%E4%B9%A0/2018-09-14%20k8s%20%E4%BE%9D%E8%B5%96%E5%BA%93%E4%B8%AD%E7%9A%84go-restful%E6%A1%86%E6%9E%B6.md
長按二維碼向我轉賬
受蘋果公司新規定影響,微信 iOS 版的贊賞功能被關閉,可透過二維碼轉賬支援公眾號。
微信掃一掃
使用小程式