Golang — RESTful框架 go-restful

go-restful

go-restful 是一个 Golang 第三方库,是一个轻量的 RESTful API 框架,基于 Golang Build-in 的 http/net 库。适用于构建灵活多变的 Web Application,Kubernetes 的 ApiServer 也使用了 go-restful。

特性

  • 支持使用路径参数进行请求→函数映射的路由
  • 可配置的路由器:默认使用 CurlyRouter 快速路由算法,也支持 RouterJSR311。
  • 提供 Request API 用于从 JSON、XML 读取路径参数、查询参数、头部参数,并转换为 Struct。
  • 提供 Response API 用于将 Struct 写入到 JSON、XML 以及 Header。
  • 支持在服务级、或路由级对请求、响应流进行过滤和拦截。
  • 不同HTTP端点上的WebServices容器
  • 支持使用过滤器自动响应 OPTIONS 请求和 CORS(跨域)请求。
  • 支持使用 RecoverHandler 自定义处理 HTTP 500 错误。
  • 支持使用 ServiceErrorHandler 自定义处理路由错误产生 HTTP 404/405/406/415 等错误。
  • 支持对请求、响应的有效负载进行编码(例如:gzip、deflate)。
  • 支持使用 CompressorProvider 注册自定义的 gzip、deflate 的读入器和输出器。
  • 支持使用 EntityReaderWriter 注册的自定义编码实现。
  • 支持 Swagger UI 编写的 API 文档。
  • 支持可配置的日志跟踪

概念

Routes

Route是由HTTP方法、URL路径和使用的MIME类型(Content-Type)和生成的MIME类型(Accept)定义的。这个包有查找最佳匹配Route的逻辑,如果找到了,就调用它的Function。

WebServices

WebService有一个Route对象集合,这些对象将流入的Http请求分派给一个函数调用。通常,WebService有一个根路径(例如/users),并为它的路由定义了常见的MIME类型。为了处理来自服务器的Http请求,必须将WebServices添加到容器中。

Containers

容器包含WebServices、Filters和用于复用http请求的http.ServeMux的集合。使用restful.add(…)restful.filter(…)将WebServices和Filters注册到默认容器中。go-rest的默认容器使用http.DefaultServeMux。您可以创建自己的Container并为特定容器创建一个新的http.Server。

Filters

过滤器动态地拦截请求和响应,以转换或使用包含在请求或响应中的信息。您可以使用过滤器来执行通用的日志记录、测量、身份验证、重定向、设置响应头等。在restfull包中,有三个hook进入请求、响应流,可以在其中添加过滤器。

Container Filters

在任意已注册的WebService之前处理这些服务。

// 为默认容器安装一个(全局)过滤器(在任意webservice之前处理)
restful.Filter(globalLogging)

WebService Filters

在WebService的任意路由之前处理。

// 安装webservice过滤器(在任意路由之前处理)
ws.Filter(webserviceLogging).Filter(measureTime)

Route Filters

在调用与路由相关的函数之前被处理。

// 安装2个链式路由过滤器(在调用findUser之前处理)
ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser))

自定义Filters

每个 Filter 必须实现一个 FilterFunction

func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain)

并使用如下语句传递请求、响应对到下一个 Filter 或 RouteFunction:

chain.ProcessFilter(req, resp)

示例

package main

import (
	"io"
	"log"
	"net/http"

	"github.com/emicklei/go-restful"
	swagger "github.com/emicklei/go-restful-swagger12"
)

type UserResource struct{}

func (u UserResource) result(request *restful.Request, response *restful.Response) {
	io.WriteString(response.ResponseWriter, "this would be a normal response")
}

func (UserResource) SwaggerDoc() map[string]string {
	return map[string]string{
		"":         "Address doc",
		"country":  "Country doc",
		"postcode": "PostCode doc",
	}
}

func (u UserResource) RegisterTo(container *restful.Container) {
	ws := new(restful.WebService)
	ws.Path("/user").Consumes("*/*").Produces("*/*")

	ws.Route(ws.GET("/{id}").
		To(u.result).
		Doc("方法描述:获取用户").
		Param(ws.PathParameter("id", "参数描述:用户ID").DataType("string")).
		Param(ws.QueryParameter("name", "用户名称").DataType("string")).
		Param(ws.HeaderParameter("token", "访问令牌").DataType("string")).
		Do(returns200, returns500))
	ws.Route(ws.POST("").To(u.result))
	ws.Route(ws.PUT("/{id}").To(u.result))
	ws.Route(ws.DELETE("/{id}").To(u.result))

	container.Add(ws)
}

func returns200(b *restful.RouteBuilder) {
	b.Returns(http.StatusOK, "OK", "success")
}

func returns500(b *restful.RouteBuilder) {
	b.Returns(http.StatusInternalServerError, "Bummer, something went wrong", nil)
}

func main() {
	wsContainer := restful.NewContainer()

	// 跨域过滤器
	cors := restful.CrossOriginResourceSharing{
		ExposeHeaders:  []string{"X-My-Header"},
		AllowedHeaders: []string{"Content-Type", "Accept"},
		AllowedMethods: []string{"GET", "POST"},
		CookiesAllowed: false,
		Container:      wsContainer}
	wsContainer.Filter(cors.Filter)

	// Add container filter to respond to OPTIONS
	wsContainer.Filter(wsContainer.OPTIONSFilter)

	config := swagger.Config{
		WebServices:    restful.DefaultContainer.RegisteredWebServices(), // you control what services are visible
		WebServicesUrl: "http://localhost:8080",
		ApiPath:        "/apidocs.json",
		ApiVersion:     "V1.0",
		// Optionally, specify where the UI is located
		SwaggerPath:     "/apidocs/",
		SwaggerFilePath: "D:/gowork/src/doublegao/experiment/restful/dist"}
	swagger.RegisterSwaggerService(config, wsContainer)
	swagger.InstallSwaggerService(config)

	u := UserResource{}
	u.RegisterTo(wsContainer)

	log.Print("start listening on localhost:8080")
	server := &http.Server{Addr: ":8080", Handler: wsContainer}
	defer server.Close()
	log.Fatal(server.ListenAndServe())

}


版权声明:本文为weixin_45804031原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。