Golang不一样的Swagger体验

zc2638 · 2021-01-11 21:26:13 · 4438 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2021-01-11 21:26:13 的主题,其中的信息可能已经有所发展或是发生改变。

Golang不一样的swagger

什么是swagger

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

swag

zc2638/swag 是一个轻量级的库,可以为Go项目生成swagger json。 没有代码生成,没有框架约束,无须使用注释信息去实现伪注解,只有一个简单的swagger结构定义。

原始代码库savaki/swag,由于作者不再维护,故在此基础上的修改版本。

使用

获取

go get github.com/zc2638/swag

Endpoint

swag提供了一个单独的程序包,endpoint用来创建一个特定的接口定义,这些接口定义可以通过swag.Endpoints(...)挂载。

在这个简单的示例中,我们生成一个接口定义来获取所有pet。接口定义只需要接口请求方式和路径,为了使swagger定义完整,需要约束返回结果。

allPets := endpoint.New(http.MethodGet, "/pet", endpoint.ResponseSuccess())

当然,也可以指定多个自定义返回结果:

allPets := endpoint.New("get", "/pet",
  endpoint.Summary("Return all the pets"),
  endpoint.Response(http.StatusOk, Pet{}, "Successful operation"),
  endpoint.Response(http.StatusInternalServerError, Error{}, "Oops ... something went wrong"),
)

Walk

Walk是简化所有接口定义遍历的方法。有关如何使用Walk方法将接口定义绑定到指定框架的路由上,请参见下面的完整示例。

api := swag.New(
    swag.Title("Swagger Petstore"),
    swag.Endpoints(post, get),
)

router := gin.Default()
// iterate over each endpoint, if we've defined a handler, we can use it to bind to the router.  We're using ```gin``
// in this example, but any web framework will do.
api.Walk(func(path string, endpoint *swagger.Endpoint) {
    h := endpoint.Handler.(func(c *gin.Context))
    path = swag.ColonPath(path)
    router.Handle(endpoint.Method, path, h)
})

完整示例

// Copyright 2020 zc2638
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package main

import (
    "io"
    "net/http"

    "github.com/zc2638/swag"
    "github.com/zc2638/swag/endpoint"
    "github.com/zc2638/swag/swagger"
)

func handle(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, req.Method+" - Insert your code here")
}

// Category example from the swagger pet store
type Category struct {
    ID   int64  `json:"category"`
    Name string `json:"name" enum:"dog,cat"`
}

// Pet example from the swagger pet store
type Pet struct {
    ID        int64    `json:"id"`
    Category  Category `json:"category"`
    Name      string   `json:"name" required:"" example:"张三" desc:"名称"`
    PhotoUrls []string `json:"photoUrls"`
    Tags      []string `json:"tags"`
    Test
}

type Test struct {
    A string `json:"a"`
}

func main() {
    post := endpoint.New("post", "/pet", endpoint.Summary("Add a new pet to the store"),
        endpoint.Handler(handle),
        endpoint.Description("Additional information on adding a pet to the store"),
        endpoint.Body(Pet{}, "Pet object that needs to be added to the store", true),
        endpoint.Response(http.StatusOK, "Successfully added pet", endpoint.Schema(Pet{})),
        endpoint.Security("petstore_auth", "read:pets", "write:pets"),
    )
    get := endpoint.New("get", "/pet/{petId}", endpoint.Summary("Find pet by ID"),
        endpoint.Handler(handle),
        endpoint.Path("petId", "integer", "ID of pet to return", true),
        endpoint.Response(http.StatusOK, "successful operation", endpoint.Schema(Pet{})),
        endpoint.Security("petstore_auth", "read:pets"),
    )

    api := swag.New(
        swag.Endpoints(post, get),
        swag.Security("petstore_auth", "read:pets"),
        swag.SecurityScheme("petstore_auth",
            swagger.OAuth2Security("accessCode", "http://example.com/oauth/authorize", "http://example.com/oauth/token"),
            swagger.OAuth2Scope("write:pets", "modify pets in your account"),
            swagger.OAuth2Scope("read:pets", "read your pets"),
        ),
    )

    for path, endpoints := range api.Paths {
        http.Handle(path, endpoints)
    }

    enableCors := true
    http.Handle("/swagger", api.Handler(enableCors))

    http.ListenAndServe(":8080", nil)
}

可以使用内置方法swag.New().Handler(false)生成解析好的Swagger JSON定义。

指定Struct Tag生成额外内容:

  • required: 是否必须
  • desc: 描述
  • description: 描述,作用同desc
  • example: 默认示例
  • enum: 枚举定义,逗号分隔

快速生成在线版本swagger

参考官方UI

Webpack

参考

Docker

docker run -p 8080:8080 -e SWAGGER_JSON_URL=https://petstore.swagger.io/v1/swagger.json swaggerapi/swagger-ui

Kubernetes

swagger-ui.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: swagger-ui
  labels:
    app: swagger-ui
spec:
  selector:
    matchLabels:
      app: swagger-ui
  template:
    metadata:
      name: swagger-ui
      labels:
        app: swagger-ui
    spec:
      containers:
        - name: swagger-ui
          image: swaggerapi/swagger-ui:latest
          env:
            - name: SWAGGER_JSON_URL
              value: 'https://petstore.swagger.io/v1/swagger.json'
---
apiVersion: v1
kind: Service
metadata:
  name: swagger-ui
  labels:
    app: swagger-ui
spec:
  ports:
    - name: swagger-ui-80
      port: 80
  selector:
    app: swagger-ui
  type: NodePort

kubectl app -f swagger-ui.yaml

最后

传送门:https://github.com/zc2638/swag


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4438 次点击  ∙  1 赞  
加入收藏 微博
1 回复  |  直到 2021-07-19 08:24:16
zc2638
zc2638 · #1 · 4年之前

增加内置UI

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传