在 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 文件。
packageuserserviceimport("github.com/emicklei/go-restful""log")typeUserstruct{ Id, Namestring}
User 类型代表我们要操作的对象。
文件中的下一个部分就是 WebService 的 API 定义。这些 API 是一组Route对象的集合,这些Route定义了如何将进来的 HTTP 请求映射到对应的处理函数。
funcNew() *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("/").To(FindUser)) service.Route(service.POST("").To(UpdateUser)) service.Route(service.PUT("/").To(CreateUser)) service.Route(service.DELETE("/").To(RemoveUser)) return service}
首先,使用一个 root URL 来初始化所有路径的 service,定义每个 Route 可以接收的MIME类型,以及可以响应的MIME类型。当然这个也可以针对每个Route单独指定。然后,service 指定它可以提供哪些路径。这里的函数调用 是 的简单写法,这个方法调用创建一个 RouteBuilder 对象。然后使用这个 RouteBuilder 对象指定对应的处理函数。
下面,就是定义每个 Route 的处理函数了。
funcFindUser(request*restful.Request,response*restful.Response) {id:= request.PathParameter("user-id") // here you would fetch user from some persistence system usr := &Userresponse.WriteEntity(usr)}
Route 的处理函数的方法声明都一样,包含一个 Restful 的 Request 和 Response,两个一对。 Request 是 http Request 对象的封装,提供了一些方便的方法。Response 是对 http ResponseWriter 的封装。这种设计方式可以将底层的 HTTP 结构开放给开发者,同时也为开发者提供了一些通用的 Restful 函数,例如 WriteEntity。WriteEntity 函数会检查请求的 Accept 头部来决定 response 的 Content-Type 头部,同时也决定了使用那种方法来序列化对象(这里就是 User 对象)。
userservice.go 文件的其他内容就是剩下的Route处理函数的定义。
funcUpdateUser(request *restful.Request, response *restful.Response){ usr :=new(User) err := request.ReadEntity(&usr)// here you would update the user with some persistence systemiferr ==nil{ response.WriteEntity(usr) }else{ response.WriteError(http.StatusInternalServerError,err) }}funcCreateUser(request *restful.Request, response *restful.Response){ usr := User err := request.ReadEntity(&usr)// here you would create the user with some persistence systemiferr ==nil{ response.WriteEntity(usr) }else{ response.WriteError(http.StatusInternalServerError,err) }}funcRemoveUser(request *restful.Request, response *restful.Response){// here you would delete the user from some persistence system}
现在,我们已经完成了 UserService 的定义和实现。下面的代码段演示了如何在一个应用中使用这个 service。
packagemainimport("github.com/emicklei/go-restful""log""net/http""userservice")funcmain(){ restful.Add(userservice.New()) log.Fatal(http.ListenAndServe(":8080",nil))}
服务启动之后,我们可以利用下面的方法测试:
默认的请求
$ curl http://localhost:8080/users/1212John Doe
带 Accpet 头部的请求
$ curl http://localhost:9090/users/12-H 'Accept: application/json'{"Id":"12","Name":"John Doe"}
新建一个User对象
$ curl http://localhost:9090/users -X POST -d '{"Id":"32","Name":"jemygraw"}' -H 'Content-Type: application/json'32jemygraw
新的一个User对象,要求返回JSON。
$ curlhttp://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
领取专属 10元无门槛券
私享最新 技术干货