Gag - 一个用Go实现的API网关(附代码)

114 阅读1分钟

Go Reference

Gag

  • Gag是一个用Go实现的HTTP API网关,Gag提供了一个声明性的接口,并且它具有高度的可配置性。

支持的功能

  • 基于路径处理请求。
  • 基于HTTP方法处理请求。
  • 处理有配置的头信息的请求。
  • 处理有配置好的头信息键的请求,同时还有值。
  • 用你自己的处理程序处理请求,该处理程序实现了API组合模式
  • 将请求路由(重定向)到不同的服务。
  • 为每个请求应用中间件。

例子

简单的路由

func main() {
    g := gag.NewGag(gag.Config{Port: 8080})
    g.Conditions.
        Path("/foo").Method(http.MethodGet).Route(&gag.RouteRequest{Url: "http://some.url/route-to", HttpMethod: http.MethodGet}, g)
    err := g.Serve()
    if err != nil {
        panic(err)
    }
}
  • 在上面的例子中,只有符合/foo 路径、具有HTTP GET方法的请求才会被路由到http://some.url/route-to

简单处理

type sampleResponse struct {
    Message string `json:"message"`
}

func sampleHandler() http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        res, err := json.Marshal(sampleResponse{Message: "sample handler!"})
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            w.Write([]byte("something went wrong.."))
        }
        w.Header().Add("Content-Type", "application/json")
        w.WriteHeader(http.StatusOK)
        w.Write(res)
    }
}

func main() {
    g := gag.NewGag(gag.Config{Port: 8080})
    g.Conditions.
        Path("/bar").Method(http.MethodPost).HandlerFunc(sampleHandler(), g)
    err := g.Serve()
    if err != nil {
        panic(err)
    }
}
  • 在上面的例子中,只有符合/bar 路径、具有HTTP POST方法的请求才会被处理。

使用中间件

func sampleTimingMiddleware() func(h http.Handler) http.Handler {
    return func(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            start := time.Now()
            h.ServeHTTP(w, r)
            end := time.Now()
            log.Printf("request time for %s: %v", r.URL.Path, end.Sub(start))
        })
    }
}

func main() {
    g := gag.NewGag(gag.Config{Port: 8080})
	g.Conditions().
		Path("/some-path").Middlewares(sampleTimingMiddleware()).HandlerFunc(sampleHandler(), g)
	err := g.Serve()
	if err != nil {
		panic(err)
	}
}
  • 由于Gag是建立在gorilla/mux之上的,所以path支持路径变量和更多的东西。 下面是一个使用path变量的示例代码:
func samplePathVariableHandler() http.HandlerFunc {

	type sampleResponse struct {
		Message string `json:"message"`
	}

	return func(w http.ResponseWriter, r *http.Request) {
		vars := gorillaMux.Vars(r)
		id, ok := vars["id"]
		if !ok {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("something went wrong.."))
		}
		res, err := json.Marshal(sampleResponse{Message: fmt.Sprintf("id: %s", id)})
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			w.Write([]byte("something went wrong.."))
		}
		w.Header().Add("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(res)
	}
}

func main() {
    g := gag.NewGag(gag.Config{Port: 8080})
	g.Conditions().
        Path("/this-is-path/{id}").HandlerFunc(samplePathVariableHandler(), g)
    err := g.Serve()
    if err != nil {
        panic(err)
    }
}