Skip to content

dyntrait/goctl-swagger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

goctl-swagger

1. 编译goctl-swagger插件

GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go install  github.com/dyntrait/[email protected]

goctl-swagger -V  

使用须知

  • 支持go-zero及goctl版本1.6.0及以后
  • support import nested api,比如在a.api定义了类型.然后在b.api导入a.api就可以使用a.api的类型.
  • 支持在group设置的路径前缀prefix
  • 支持tag:header,path,form,json.建议gozero的tag放在最前面.其他验证库的tag放在最后面

举例

type IndexRequset {
	TestPath   string `path:"testPath"`
	TestForm   string `form:"testForm"`
	TestHeader string `header:"testHeader"`
	TestJson   string `json:"testJson"`
}

type IndexResponse {
	Info interface{} `json:"info"`
}

service api-api {
	@doc "测试页"
	@handler test
	post /:testPath(IndexRequset) returns (IndexResponse)
}

在swagger里将生成如下请求

curl -X 'POST' \
  'http://127.0.0.1:18888/path1?testForm=q1' \
  -H 'accept: application/json' \
  -H 'testHeader: h1' \
  -H 'Content-Type: application/json' \
  -d '{
  "testJson": "nick"
}'

2. 配置环境

将$GOPATH/bin中的goctl-swagger添加到环境变量

3. 使用姿势

  • 创建api文件
    info(
    	title: "type title here"
    	desc: "type desc here"
    	author: "type author here"
    	email: "type email here"
    	version: "type version here"
    )
    
    
    type (
    	RegisterReq {
    		Username string `json:"username"`
    		Password string `json:"password"`
    		Mobile string `json:"mobile"`
    	}
    	
    	LoginReq {
    		Username string `json:"username"`
    		Password string `json:"password"`
    	}
    	
    	UserInfoReq {
    		Id string `path:"id"`
    	}
    	
    	UserInfoReply {
    		Name string `json:"name"`
    		Age int `json:"age"`
    		Birthday string `json:"birthday"`
    		Description string `json:"description"`
    		Tag []string `json:"tag"`
    	}
    	
    	UserSearchReq {
    		KeyWord string `form:"keyWord"`
    	}
    )
    
    service user-api {
    	@doc(
    		summary: "注册"
    	)
    	@handler register
    	post /api/user/register (RegisterReq)
    	
    	@doc(
    		summary: "登录"
    	)
    	@handler login
    	post /api/user/login (LoginReq)
    	
    	@doc(
    		summary: "获取用户信息"
    	)
    	@handler getUserInfo
    	get /api/user/:id (UserInfoReq) returns (UserInfoReply)
    	
    	@doc(
    		summary: "用户搜索"
    	)
    	@handler searchUser
    	get /api/user/search (UserSearchReq) returns (UserInfoReply)
    }
  • 生成swagger.json 文件
    $ goctl api plugin -plugin goctl-swagger="swagger -filename user.json" -api user.api -dir .
  • 指定Host,basePath api-host-and-base-path
    $ goctl api plugin -plugin goctl-swagger="swagger -filename user.json -host 127.0.0.2 -basepath /" -api user.api -dir .
  • swagger ui 查看生成的文档
     $ docker run --rm -p 8083:8080 -e SWAGGER_JSON=/foo/user.json -v $PWD:/foo swaggerapi/swagger-ui
  • Swagger Codegen 生成客户端调用代码(go,javascript,php)
    for l in go javascript php; do
      docker run --rm -v "$(pwd):/go-work" swaggerapi/swagger-codegen-cli generate \
        -i "/go-work/rest.swagger.json" \
        -l "$l" \
        -o "/go-work/clients/$l"
    done

4. 结合go-zero使用自动生成接口文档

具体可参考 gozero-template

  • 定义swagger, swagger-json接口

    	@handler swag
    	get /swagger() returns()
    	@handler swagJson
    	get /swagger-json() returns()
    

    注 /swagger, /swagger-json地址可自己定义,如需自定义,需修改goctl-swagger的excludePaths取消解析路由

  • 修改生成后的Handler

    swaghandler.go

    func swagHandler(ctx *svc.ServiceContext) http.HandlerFunc {
    	l := logic.NewSwagLogic(context.TODO(), ctx)
    	return l.Swag
    }

    swagjsonhandler.go

    func swagJsonHandler(ctx *svc.ServiceContext) http.HandlerFunc {
    	return func(w http.ResponseWriter, r *http.Request) {
    		w.Header().Set("Content-Type", "application/json; charset=utf-8")
    		_, _ = w.Write(logic.SwagByte)
    	}
    }
  • 修改生成后的logic

    swagjsonlogic.go

    type SwagjsonLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    }

    swaglogic.go

    type SwagLogic struct {
    	logx.Logger
    	ctx    context.Context
    	svcCtx *svc.ServiceContext
    	Swag   http.HandlerFunc
    }
    
    const swagFilePath = "app/rest/pkg/swag/swag.json"
    
    var SwagByte json.RawMessage
    
    func init() {
    	swagFile, err := os.Open(swagFilePath)
    	if err != nil {
    		fmt.Println(err)
    	}
    	defer swagFile.Close()
    	SwagByte, err = ioutil.ReadAll(swagFile)
    	if err != nil {
    		fmt.Println(err)
    	}
    }
    
    func NewSwagLogic(ctx context.Context, svcCtx *svc.ServiceContext) SwagLogic {
    	return SwagLogic{
    		Logger: logx.WithContext(ctx),
    		ctx:    ctx,
    		svcCtx: svcCtx,
    		Swag:   swag.Doc("/swag", hutils.GetEnv("env", "alpha"), SwagByte),
    	}
    }

    swag.go

    type Opts func(*swaggerConfig)
    
    // SwaggerOpts configures the Doc middlewares.
    type swaggerConfig struct {
    	// SpecURL the url to find the spec for
    	SpecURL string
    	// SwaggerHost for the js that generates the swagger ui site, defaults to: http://petstore.swagger.io/
    	SwaggerHost string
    }
    
    func Doc(basePath, env string, swaggerJSON []byte, opts ...Opts) http.HandlerFunc {
    	config := &swaggerConfig{
    		SpecURL:     basePath + "-json",
    		SwaggerHost: "https://petstore.swagger.io"}
    	for _, opt := range opts {
    		opt(config)
    	}
    	// swagger json
    	responseSwaggerJSON := swaggerJSON
    	responseSwaggerJSON = responseSwaggerJSON
    
    	// swagger html
    	tmpl := template.Must(template.New("swaggerdoc").Parse(swaggerTemplateV2))
    	buf := bytes.NewBuffer(nil)
    	_ = tmpl.Execute(buf, config)
    	uiHTML := buf.Bytes()
    
    	// permission
    	needPermission := false
    	if env == "prod" {
    		needPermission = true
    		responseSwaggerJSON = []byte(strings.Replace(
    			string(swaggerJSON),
    			`"schemes": [
        "http"
      ],`,
    			`"schemes": [
        "https"
      ],`,
    			1))
    	}
    
    	return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
    		if r.URL.Path == basePath {
    			if needPermission {
    				rw.WriteHeader(http.StatusOK)
    				rw.Header().Set("Content-Type", "text/plain")
    				_, _ = rw.Write([]byte("Swagger not open on prod"))
    				return
    			}
    
    			rw.Header().Set("Content-Type", "text/html; charset=utf-8")
    			_, _ = rw.Write(uiHTML)
    
    			rw.WriteHeader(http.StatusOK)
    			return
    		}
    	})
    }
    
    const swaggerTemplateV2 = `
    	<!-- HTML for static distribution bundle build -->
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>API documentation</title>
        <link rel="stylesheet" type="text/css" href="{{ .SwaggerHost }}/swagger-ui.css" >
        <link rel="icon" type="image/png" href="{{ .SwaggerHost }}/favicon-32x32.png" sizes="32x32" />
        <link rel="icon" type="image/png" href="{{ .SwaggerHost }}/favicon-16x16.png" sizes="16x16" />
        <style>
          html
          {
            box-sizing: border-box;
            overflow: -moz-scrollbars-vertical;
            overflow-y: scroll;
          }
    
          *,
          *:before,
          *:after
          {
            box-sizing: inherit;
          }
    
          body
          {
            margin:0;
            background: #fafafa;
          }
        </style>
      </head>
    
      <body>
        <div id="swagger-ui"></div>
    
        <script src="{{ .SwaggerHost }}/swagger-ui-bundle.js"> </script>
        <script src="{{ .SwaggerHost }}/swagger-ui-standalone-preset.js"> </script>
        <script>
        window.onload = function() {
          // Begin Swagger UI call region
          const ui = SwaggerUIBundle({
            "dom_id": "#swagger-ui",
            deepLinking: true,
            presets: [
              SwaggerUIBundle.presets.apis,
              SwaggerUIStandalonePreset
            ],
            plugins: [
              SwaggerUIBundle.plugins.DownloadUrl
            ],
            layout: "StandaloneLayout",
    		validatorUrl: null,
            url: "{{ .SpecURL }}",
          })
    
          // End Swagger UI call region
          window.ui = ui
        }
      </script>
      </body>
    </html>`
    

About

通过 api 文件生成 swagger 文档

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages