├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .goreleaser.yml ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── example ├── basic │ ├── api │ │ └── api.go │ ├── docs │ │ ├── docs.go │ │ ├── swagger.json │ │ └── swagger.yaml │ ├── main.go │ └── web │ │ └── handler.go ├── gzipped │ ├── docs │ │ ├── docs.go │ │ ├── swagger.json │ │ └── swagger.yaml │ └── main.go └── multiple │ ├── README.md │ ├── api │ ├── v1 │ │ ├── example.go │ │ └── main.go │ └── v2 │ │ ├── example.go │ │ └── main.go │ ├── docs │ ├── v1_docs.go │ ├── v1_swagger.json │ ├── v1_swagger.yaml │ ├── v2_docs.go │ ├── v2_swagger.json │ └── v2_swagger.yaml │ └── main.go ├── go.mod ├── go.sum ├── swagger.go └── swagger_test.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | go: [ '1.17.x', '1.18.x','1.19.x', '1.20.x' ] 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@master 17 | - name: Set up Go 18 | uses: actions/setup-go@v1 19 | with: 20 | go-version: ${{ matrix.go }} 21 | - name: test 22 | run: go test -coverprofile=coverage.txt -covermode=atomic 23 | - name: coverage 24 | run: bash <(curl -s https://codecov.io/bash) 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | dist 13 | 14 | .idea 15 | vendor 16 | .envrc 17 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | builds: 2 | - skip: true 3 | snapshot: 4 | name_template: "{{ .Tag }}-next" 5 | changelog: 6 | sort: asc 7 | filters: 8 | exclude: 9 | - '^docs:' 10 | - '^test:' 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Swaggo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Describe the PR** 2 | e.g. add cool parser. 3 | 4 | **Relation issue** 5 | e.g. https://github.com/swaggo/gin-swagger/pull/123/files 6 | 7 | **Additional context** 8 | Add any other context about the problem here. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gin-swagger 2 | 3 | gin middleware to automatically generate RESTful API documentation with Swagger 2.0. 4 | 5 | [](https://github.com/features/actions) 6 | [](https://codecov.io/gh/swaggo/gin-swagger) 7 | [](https://goreportcard.com/report/github.com/swaggo/gin-swagger) 8 | [](https://godoc.org/github.com/swaggo/gin-swagger) 9 | [](https://github.com/swaggo/gin-swagger/releases) 10 | 11 | ## Usage 12 | 13 | ### Start using it 14 | 15 | 1. Add comments to your API source code, [See Declarative Comments Format](https://github.com/swaggo/swag/blob/master/README.md#declarative-comments-format). 16 | 2. Download [Swag](https://github.com/swaggo/swag) for Go by using: 17 | 18 | ```sh 19 | go get -u github.com/swaggo/swag/cmd/swag 20 | ``` 21 | 22 | Starting in Go 1.17, installing executables with `go get` is deprecated. `go install` may be used instead: 23 | 24 | ```sh 25 | go install github.com/swaggo/swag/cmd/swag@latest 26 | ``` 27 | 28 | 3. Run the [Swag](https://github.com/swaggo/swag) at your Go project root path(for instance `~/root/go-project-name`), 29 | [Swag](https://github.com/swaggo/swag) will parse comments and generate required files(`docs` folder and `docs/doc.go`) 30 | at `~/root/go-project-name/docs`. 31 | 32 | ```sh 33 | swag init 34 | ``` 35 | 36 | 4. Download [gin-swagger](https://github.com/swaggo/gin-swagger) by using: 37 | 38 | ```sh 39 | go get -u github.com/swaggo/gin-swagger 40 | go get -u github.com/swaggo/files 41 | ``` 42 | 43 | Import following in your code: 44 | 45 | ```go 46 | import "github.com/swaggo/gin-swagger" // gin-swagger middleware 47 | import "github.com/swaggo/files" // swagger embed files 48 | 49 | ``` 50 | 51 | ### Canonical example: 52 | 53 | Now assume you have implemented a simple api as following: 54 | 55 | ```go 56 | // A get function which returns a hello world string by json 57 | func Helloworld(g *gin.Context) { 58 | g.JSON(http.StatusOK,"helloworld") 59 | } 60 | 61 | ``` 62 | 63 | So how to use gin-swagger on api above? Just follow the following guide. 64 | 65 | 1. Add Comments for apis and main function with gin-swagger rules like following: 66 | 67 | ```go 68 | // @BasePath /api/v1 69 | 70 | // PingExample godoc 71 | // @Summary ping example 72 | // @Schemes 73 | // @Description do ping 74 | // @Tags example 75 | // @Accept json 76 | // @Produce json 77 | // @Success 200 {string} Helloworld 78 | // @Router /example/helloworld [get] 79 | func Helloworld(g *gin.Context) { 80 | g.JSON(http.StatusOK,"helloworld") 81 | } 82 | ``` 83 | 84 | 2. Use `swag init` command to generate a docs, docs generated will be stored at `docs/`. 85 | 3. import the docs like this: 86 | I assume your project named `github.com/go-project-name/docs`. 87 | 88 | ```go 89 | import ( 90 | docs "github.com/go-project-name/docs" 91 | ) 92 | ``` 93 | 94 | 4. build your application and after that, go to http://localhost:8080/swagger/index.html ,you to see your Swagger UI. 95 | 96 | 5. The full code and folder relatives here: 97 | 98 | ```go 99 | package main 100 | 101 | import ( 102 | "github.com/gin-gonic/gin" 103 | docs "github.com/go-project-name/docs" 104 | swaggerfiles "github.com/swaggo/files" 105 | ginSwagger "github.com/swaggo/gin-swagger" 106 | "net/http" 107 | ) 108 | // @BasePath /api/v1 109 | 110 | // PingExample godoc 111 | // @Summary ping example 112 | // @Schemes 113 | // @Description do ping 114 | // @Tags example 115 | // @Accept json 116 | // @Produce json 117 | // @Success 200 {string} Helloworld 118 | // @Router /example/helloworld [get] 119 | func Helloworld(g *gin.Context) { 120 | g.JSON(http.StatusOK,"helloworld") 121 | } 122 | 123 | func main() { 124 | r := gin.Default() 125 | docs.SwaggerInfo.BasePath = "/api/v1" 126 | v1 := r.Group("/api/v1") 127 | { 128 | eg := v1.Group("/example") 129 | { 130 | eg.GET("/helloworld",Helloworld) 131 | } 132 | } 133 | r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) 134 | r.Run(":8080") 135 | 136 | } 137 | ``` 138 | 139 | Demo project tree, `swag init` is run at relative `.` 140 | 141 | ``` 142 | . 143 | ├── docs 144 | │ ├── docs.go 145 | │ ├── swagger.json 146 | │ └── swagger.yaml 147 | ├── go.mod 148 | ├── go.sum 149 | └── main.go 150 | ``` 151 | ## Project with Nested Directory 152 | ``` 153 | . 154 | ├── cmd 155 | │ └── ginsimple 156 | │ └── main.go 157 | ├── docs 158 | │ ├── docs.go 159 | │ ├── swagger.json 160 | │ └── swagger.yaml 161 | ├── go.mod 162 | ├── go.sum 163 | └── internal 164 | ├── handlers 165 | │ ├── helloWorld.go 166 | │ └── userHandler.go 167 | └── models 168 | ├── profile.go 169 | └── user.go 170 | ``` 171 | Inorder generate swagger docs for projects with nested directories run the following command 172 | ```bash 173 | swag init -g ./cmd/ginsimple/main.go -o cmd/docs 174 | ``` 175 | `-o` will set the auto generated file to the specified path 176 | 177 | 178 | ## Multiple APIs 179 | 180 | This feature was introduced in swag v1.7.9 181 | 182 | ## Configuration 183 | 184 | You can configure Swagger using different configuration options 185 | 186 | ```go 187 | func main() { 188 | r := gin.New() 189 | 190 | ginSwagger.WrapHandler(swaggerfiles.Handler, 191 | ginSwagger.URL("http://localhost:8080/swagger/doc.json"), 192 | ginSwagger.DefaultModelsExpandDepth(-1)) 193 | 194 | r.Run() 195 | } 196 | ``` 197 | 198 | | Option | Type | Default | Description | 199 | | ------------------------ | ------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 200 | | URL | string | "doc.json" | URL pointing to API definition | 201 | | DocExpansion | string | "list" | Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing). | 202 | | DeepLinking | bool | true | If set to true, enables deep linking for tags and operations. See the Deep Linking documentation for more information. | 203 | | DefaultModelsExpandDepth | int | 1 | Default expansion depth for models (set to -1 completely hide the models). | 204 | | InstanceName | string | "swagger" | The instance name of the swagger document. If multiple different swagger instances should be deployed on one gin router, ensure that each instance has a unique name (use the _--instanceName_ parameter to generate swagger documents with _swag init_). | 205 | | PersistAuthorization | bool | false | If set to true, it persists authorization data and it would not be lost on browser close/refresh. | 206 | | Oauth2DefaultClientID | string | "" | If set, it's used to prepopulate the _client_id_ field of the OAuth2 Authorization dialog. | 207 | | Oauth2UsePkce | bool | false | If set to true, it enables Proof Key for Code Exchange to enhance security for OAuth public clients. | -------------------------------------------------------------------------------- /example/basic/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | "github.com/swaggo/swag/example/basic/web" 7 | ) 8 | 9 | // 10 | // @Summary Add a new pet to the store 11 | // @Description get string by ID 12 | // @Accept json 13 | // @Produce json 14 | // @Param some_id path int true "Some ID" 15 | // @Success 200 {string} string "ok" 16 | // @Failure 400 {object} web.APIError "We need ID!!" 17 | // @Failure 404 {object} web.APIError "Can not find ID" 18 | // @Router /testapi/get-string-by-int/{some_id} [get] 19 | func GetStringByInt(c *gin.Context) { 20 | err := web.APIError{} 21 | fmt.Println(err) 22 | } 23 | 24 | // @Description get struct array by ID 25 | // @Accept json 26 | // @Produce json 27 | // @Param some_id path string true "Some ID" 28 | // @Param offset query int true "Offset" 29 | // @Param limit query int true "Limit" 30 | // @Success 200 {string} string "ok" 31 | // @Failure 400 {object} web.APIError "We need ID!!" 32 | // @Failure 404 {object} web.APIError "Can not find ID" 33 | // @Router /testapi/get-struct-array-by-string/{some_id} [get] 34 | func GetStructArrayByString(c *gin.Context) { 35 | 36 | } 37 | 38 | type Pet3 struct { 39 | ID int `json:"id"` 40 | } 41 | -------------------------------------------------------------------------------- /example/basic/docs/docs.go: -------------------------------------------------------------------------------- 1 | // Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT 2 | // This file was generated by swaggo/swag 3 | package docs 4 | 5 | import "github.com/swaggo/swag" 6 | 7 | const docTemplate_swagger = `{ 8 | "schemes": {{ marshal .Schemes }}, 9 | "swagger": "2.0", 10 | "info": { 11 | "description": "{{escape .Description}}", 12 | "title": "{{.Title}}", 13 | "termsOfService": "http://swagger.io/terms/", 14 | "contact": { 15 | "name": "API Support", 16 | "url": "http://www.swagger.io/support", 17 | "email": "support@swagger.io" 18 | }, 19 | "license": { 20 | "name": "Apache 2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 22 | }, 23 | "version": "{{.Version}}" 24 | }, 25 | "host": "{{.Host}}", 26 | "basePath": "{{.BasePath}}", 27 | "paths": { 28 | "/testapi/get-string-by-int/{some_id}": { 29 | "get": { 30 | "description": "get string by ID", 31 | "consumes": [ 32 | "application/json" 33 | ], 34 | "produces": [ 35 | "application/json" 36 | ], 37 | "summary": "Add a new pet to the store", 38 | "parameters": [ 39 | { 40 | "type": "integer", 41 | "description": "Some ID", 42 | "name": "some_id", 43 | "in": "path", 44 | "required": true 45 | } 46 | ], 47 | "responses": { 48 | "200": { 49 | "description": "ok", 50 | "schema": { 51 | "type": "string" 52 | } 53 | }, 54 | "400": { 55 | "description": "We need ID!!", 56 | "schema": { 57 | "$ref": "#/definitions/web.APIError" 58 | } 59 | }, 60 | "404": { 61 | "description": "Can not find ID", 62 | "schema": { 63 | "$ref": "#/definitions/web.APIError" 64 | } 65 | } 66 | } 67 | } 68 | }, 69 | "/testapi/get-struct-array-by-string/{some_id}": { 70 | "get": { 71 | "description": "get struct array by ID", 72 | "consumes": [ 73 | "application/json" 74 | ], 75 | "produces": [ 76 | "application/json" 77 | ], 78 | "parameters": [ 79 | { 80 | "type": "string", 81 | "description": "Some ID", 82 | "name": "some_id", 83 | "in": "path", 84 | "required": true 85 | }, 86 | { 87 | "type": "integer", 88 | "description": "Offset", 89 | "name": "offset", 90 | "in": "query", 91 | "required": true 92 | }, 93 | { 94 | "type": "integer", 95 | "description": "Offset", 96 | "name": "limit", 97 | "in": "query", 98 | "required": true 99 | } 100 | ], 101 | "responses": { 102 | "200": { 103 | "description": "ok", 104 | "schema": { 105 | "type": "string" 106 | } 107 | }, 108 | "400": { 109 | "description": "We need ID!!", 110 | "schema": { 111 | "$ref": "#/definitions/web.APIError" 112 | } 113 | }, 114 | "404": { 115 | "description": "Can not find ID", 116 | "schema": { 117 | "$ref": "#/definitions/web.APIError" 118 | } 119 | } 120 | } 121 | } 122 | } 123 | }, 124 | "definitions": { 125 | "web.APIError": { 126 | "type": "object", 127 | "properties": { 128 | "errorCode": { 129 | "type": "integer" 130 | }, 131 | "errorMessage": { 132 | "type": "string" 133 | } 134 | } 135 | } 136 | } 137 | }` 138 | 139 | // SwaggerInfo_swagger holds exported Swagger Info so clients can modify it 140 | var SwaggerInfo_swagger = &swag.Spec{ 141 | Version: "1.0", 142 | Host: "petstore.swagger.io:8080", 143 | BasePath: "/v2", 144 | Schemes: []string{}, 145 | Title: "Swagger Example API", 146 | Description: "This is a sample server Petstore server.", 147 | InfoInstanceName: "swagger", 148 | SwaggerTemplate: docTemplate_swagger, 149 | } 150 | 151 | func init() { 152 | swag.Register(SwaggerInfo_swagger.InstanceName(), SwaggerInfo_swagger) 153 | } 154 | -------------------------------------------------------------------------------- /example/basic/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io:8080", 19 | "basePath": "/v2", 20 | "paths": { 21 | "/testapi/get-string-by-int/{some_id}": { 22 | "get": { 23 | "description": "get string by ID", 24 | "consumes": [ 25 | "application/json" 26 | ], 27 | "produces": [ 28 | "application/json" 29 | ], 30 | "summary": "Add a new pet to the store", 31 | "parameters": [ 32 | { 33 | "type": "integer", 34 | "description": "Some ID", 35 | "name": "some_id", 36 | "in": "path", 37 | "required": true 38 | } 39 | ], 40 | "responses": { 41 | "200": { 42 | "description": "ok", 43 | "schema": { 44 | "type": "string" 45 | } 46 | }, 47 | "400": { 48 | "description": "We need ID!!", 49 | "schema": { 50 | "$ref": "#/definitions/web.APIError" 51 | } 52 | }, 53 | "404": { 54 | "description": "Can not find ID", 55 | "schema": { 56 | "$ref": "#/definitions/web.APIError" 57 | } 58 | } 59 | } 60 | } 61 | }, 62 | "/testapi/get-struct-array-by-string/{some_id}": { 63 | "get": { 64 | "description": "get struct array by ID", 65 | "consumes": [ 66 | "application/json" 67 | ], 68 | "produces": [ 69 | "application/json" 70 | ], 71 | "parameters": [ 72 | { 73 | "type": "string", 74 | "description": "Some ID", 75 | "name": "some_id", 76 | "in": "path", 77 | "required": true 78 | }, 79 | { 80 | "type": "integer", 81 | "description": "Offset", 82 | "name": "offset", 83 | "in": "query", 84 | "required": true 85 | }, 86 | { 87 | "type": "integer", 88 | "description": "Offset", 89 | "name": "limit", 90 | "in": "query", 91 | "required": true 92 | } 93 | ], 94 | "responses": { 95 | "200": { 96 | "description": "ok", 97 | "schema": { 98 | "type": "string" 99 | } 100 | }, 101 | "400": { 102 | "description": "We need ID!!", 103 | "schema": { 104 | "$ref": "#/definitions/web.APIError" 105 | } 106 | }, 107 | "404": { 108 | "description": "Can not find ID", 109 | "schema": { 110 | "$ref": "#/definitions/web.APIError" 111 | } 112 | } 113 | } 114 | } 115 | } 116 | }, 117 | "definitions": { 118 | "web.APIError": { 119 | "type": "object", 120 | "properties": { 121 | "errorCode": { 122 | "type": "integer" 123 | }, 124 | "errorMessage": { 125 | "type": "string" 126 | } 127 | } 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /example/basic/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v2 2 | definitions: 3 | web.APIError: 4 | properties: 5 | errorCode: 6 | type: integer 7 | errorMessage: 8 | type: string 9 | type: object 10 | host: petstore.swagger.io:8080 11 | info: 12 | contact: 13 | email: support@swagger.io 14 | name: API Support 15 | url: http://www.swagger.io/support 16 | description: This is a sample server Petstore server. 17 | license: 18 | name: Apache 2.0 19 | url: http://www.apache.org/licenses/LICENSE-2.0.html 20 | termsOfService: http://swagger.io/terms/ 21 | title: Swagger Example API 22 | version: "1.0" 23 | paths: 24 | /testapi/get-string-by-int/{some_id}: 25 | get: 26 | consumes: 27 | - application/json 28 | description: get string by ID 29 | parameters: 30 | - description: Some ID 31 | in: path 32 | name: some_id 33 | required: true 34 | type: integer 35 | produces: 36 | - application/json 37 | responses: 38 | "200": 39 | description: ok 40 | schema: 41 | type: string 42 | "400": 43 | description: We need ID!! 44 | schema: 45 | $ref: '#/definitions/web.APIError' 46 | "404": 47 | description: Can not find ID 48 | schema: 49 | $ref: '#/definitions/web.APIError' 50 | summary: Add a new pet to the store 51 | /testapi/get-struct-array-by-string/{some_id}: 52 | get: 53 | consumes: 54 | - application/json 55 | description: get struct array by ID 56 | parameters: 57 | - description: Some ID 58 | in: path 59 | name: some_id 60 | required: true 61 | type: string 62 | - description: Offset 63 | in: query 64 | name: offset 65 | required: true 66 | type: integer 67 | - description: Offset 68 | in: query 69 | name: limit 70 | required: true 71 | type: integer 72 | produces: 73 | - application/json 74 | responses: 75 | "200": 76 | description: ok 77 | schema: 78 | type: string 79 | "400": 80 | description: We need ID!! 81 | schema: 82 | $ref: '#/definitions/web.APIError' 83 | "404": 84 | description: Can not find ID 85 | schema: 86 | $ref: '#/definitions/web.APIError' 87 | swagger: "2.0" 88 | -------------------------------------------------------------------------------- /example/basic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | "github.com/swaggo/gin-swagger" 7 | 8 | "github.com/swaggo/gin-swagger/example/basic/api" 9 | 10 | _ "github.com/swaggo/gin-swagger/example/basic/docs" 11 | ) 12 | 13 | // @title Swagger Example API 14 | // @version 1.0 15 | // @description This is a sample server Petstore server. 16 | // @termsOfService http://swagger.io/terms/ 17 | 18 | // @contact.name API Support 19 | // @contact.url http://www.swagger.io/support 20 | // @contact.email support@swagger.io 21 | 22 | // @license.name Apache 2.0 23 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 24 | 25 | // @host petstore.swagger.io:8080 26 | // @BasePath /v2 27 | func main() { 28 | r := gin.New() 29 | 30 | r.GET("/v2/testapi/get-string-by-int/:some_id", api.GetStringByInt) 31 | r.GET("/v2/testapi/get-struct-array-by-string/:some_id", api.GetStructArrayByString) 32 | 33 | url := ginSwagger.URL("http://petstore.swagger.io:8080/swagger/doc.json") // The url pointing to API definition 34 | r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 35 | 36 | r.Run() 37 | } 38 | -------------------------------------------------------------------------------- /example/basic/web/handler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | // @hello 4 | // yo yo yo yo 5 | type Pet struct { 6 | ID int `json:"id"` 7 | Category struct { 8 | ID int `json:"id"` 9 | Name string `json:"name"` 10 | } `json:"category"` 11 | Name string `json:"name"` 12 | PhotoUrls []string `json:"photoUrls"` 13 | Tags []struct { 14 | ID int `json:"id"` 15 | Name string `json:"name"` 16 | } `json:"tags"` 17 | Status string `json:"status"` 18 | } 19 | 20 | type Pet2 struct { 21 | ID int `json:"id"` 22 | } 23 | 24 | type APIError struct { 25 | ErrorCode int 26 | ErrorMessage string 27 | } 28 | -------------------------------------------------------------------------------- /example/gzipped/docs/docs.go: -------------------------------------------------------------------------------- 1 | // Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT 2 | // This file was generated by swaggo/swag 3 | package docs 4 | 5 | import "github.com/swaggo/swag" 6 | 7 | const docTemplate_swagger = `{ 8 | "schemes": {{ marshal .Schemes }}, 9 | "swagger": "2.0", 10 | "info": { 11 | "description": "{{escape .Description}}", 12 | "title": "{{.Title}}", 13 | "termsOfService": "http://swagger.io/terms/", 14 | "contact": { 15 | "name": "API Support", 16 | "url": "http://www.swagger.io/support", 17 | "email": "support@swagger.io" 18 | }, 19 | "license": { 20 | "name": "Apache 2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 22 | }, 23 | "version": "{{.Version}}" 24 | }, 25 | "host": "{{.Host}}", 26 | "basePath": "{{.BasePath}}", 27 | "paths": {} 28 | }` 29 | 30 | // SwaggerInfo_swagger holds exported Swagger Info so clients can modify it 31 | var SwaggerInfo_swagger = &swag.Spec{ 32 | Version: "1.0", 33 | Host: "petstore.swagger.io", 34 | BasePath: "/v2", 35 | Schemes: []string{}, 36 | Title: "Swagger Example API", 37 | Description: "This is a sample server Petstore server.", 38 | InfoInstanceName: "swagger", 39 | SwaggerTemplate: docTemplate_swagger, 40 | } 41 | 42 | func init() { 43 | swag.Register(SwaggerInfo_swagger.InstanceName(), SwaggerInfo_swagger) 44 | } 45 | -------------------------------------------------------------------------------- /example/gzipped/docs/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server Petstore server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "host": "petstore.swagger.io", 19 | "basePath": "/v2", 20 | "paths": {} 21 | } -------------------------------------------------------------------------------- /example/gzipped/docs/swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v2 2 | host: petstore.swagger.io 3 | info: 4 | contact: 5 | email: support@swagger.io 6 | name: API Support 7 | url: http://www.swagger.io/support 8 | description: This is a sample server Petstore server. 9 | license: 10 | name: Apache 2.0 11 | url: http://www.apache.org/licenses/LICENSE-2.0.html 12 | termsOfService: http://swagger.io/terms/ 13 | title: Swagger Example API 14 | version: "1.0" 15 | paths: {} 16 | swagger: "2.0" 17 | -------------------------------------------------------------------------------- /example/gzipped/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-contrib/gzip" 5 | "github.com/gin-gonic/gin" 6 | swaggerFiles "github.com/swaggo/files" 7 | "github.com/swaggo/gin-swagger" 8 | 9 | _ "github.com/swaggo/gin-swagger/example/basic/docs" 10 | ) 11 | 12 | // @title Swagger Example API 13 | // @version 1.0 14 | // @description This is a sample server Petstore server. 15 | // @termsOfService http://swagger.io/terms/ 16 | 17 | // @contact.name API Support 18 | // @contact.url http://www.swagger.io/support 19 | // @contact.email support@swagger.io 20 | 21 | // @license.name Apache 2.0 22 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 23 | 24 | // @host petstore.swagger.io 25 | // @BasePath /v2 26 | func main() { 27 | r := gin.New() 28 | 29 | r.Use(gzip.Gzip(gzip.BestSpeed)) 30 | 31 | url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") // The url pointing to API definition 32 | r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url)) 33 | 34 | r.Run() 35 | } 36 | -------------------------------------------------------------------------------- /example/multiple/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Multiple API feature 3 | Since swag 1.7.9 we are allowing registration of multiple endpoints into the same server. 4 | 5 | Generate documentation for v1 endpoints 6 | ```shell 7 | swag i -g main.go -dir api/v1 --instanceName v1 8 | ``` 9 | 10 | 11 | Generate documentation for v2 endpoints 12 | ```shell 13 | swag i -g main.go -dir api/v2 --instanceName v2 14 | ``` 15 | 16 | Run example 17 | ```shell 18 | go run main.go 19 | ``` 20 | 21 | Now you can access the v1 swagger here [http://localhost:8080/swagger/v1/index.html](http://localhost:8080/swagger/v1/index.html) , 22 | and v2 swagger here [http://localhost:8080/swagger/v2/index.html](http://localhost:8080/swagger/v2/index.html) 23 | 24 | -------------------------------------------------------------------------------- /example/multiple/api/v1/example.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | type Book struct { 8 | ID int `json:"id,omitempty"` 9 | Title string `json:"title"` 10 | Author string `json:"author"` 11 | Year *uint16 `json:"year"` 12 | } 13 | 14 | // 15 | // @Summary Get a list of books in the the store 16 | // @Description get string by ID 17 | // @Accept json 18 | // @Produce json 19 | // @Success 200 {array} Book "ok" 20 | // @Router /books [get] 21 | func GetBooks(ctx *gin.Context) { 22 | ctx.JSON(200, []Book{ 23 | {ID: 1, Title: "Book 1", Author: "Author 1", Year: nil}, 24 | {ID: 2, Title: "Book 2", Author: "Author 2", Year: nil}, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /example/multiple/api/v1/main.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // @title Swagger Example API 8 | // @version 1.0 9 | // @description This is a sample server. 10 | // @termsOfService http://swagger.io/terms/ 11 | 12 | // @contact.name API Support 13 | // @contact.url http://www.swagger.io/support 14 | // @contact.email support@swagger.io 15 | 16 | // @license.name Apache 2.0 17 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 18 | 19 | // @BasePath /v1 20 | 21 | func Register(router *gin.Engine) { 22 | v1 := router.Group("v1") 23 | 24 | v1.GET("/books", GetBooks) 25 | } 26 | -------------------------------------------------------------------------------- /example/multiple/api/v2/example.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | type Book struct { 8 | ID int `json:"id,omitempty"` 9 | Title string `json:"title"` 10 | Author string `json:"author"` 11 | Year *uint16 `json:"year"` 12 | } 13 | 14 | // 15 | // @Summary Get a list of books in the the store 16 | // @Description get string by ID 17 | // @Accept json 18 | // @Produce json 19 | // @Success 200 {array} Book "ok" 20 | // @Router /books [get] 21 | func GetBooks(ctx *gin.Context) { 22 | ctx.JSON(200, []Book{ 23 | {ID: 1, Title: "Book 3", Author: "Author 3", Year: nil}, 24 | {ID: 2, Title: "Book 4", Author: "Author 4", Year: nil}, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /example/multiple/api/v2/main.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // @title Swagger Example API 8 | // @version 2.0 9 | // @description This is a sample server. 10 | // @termsOfService http://swagger.io/terms/ 11 | 12 | // @contact.name API Support 13 | // @contact.url http://www.swagger.io/support 14 | // @contact.email support@swagger.io 15 | 16 | // @license.name Apache 2.0 17 | // @license.url http://www.apache.org/licenses/LICENSE-2.0.html 18 | 19 | // @BasePath /v2 20 | 21 | func Register(router *gin.Engine) { 22 | v2 := router.Group("v2") 23 | 24 | v2.GET("/books", GetBooks) 25 | } 26 | -------------------------------------------------------------------------------- /example/multiple/docs/v1_docs.go: -------------------------------------------------------------------------------- 1 | // Package docs GENERATED BY SWAG; DO NOT EDIT 2 | // This file was generated by swaggo/swag 3 | package docs 4 | 5 | import "github.com/swaggo/swag" 6 | 7 | const docTemplatev1 = `{ 8 | "schemes": {{ marshal .Schemes }}, 9 | "swagger": "2.0", 10 | "info": { 11 | "description": "{{escape .Description}}", 12 | "title": "{{.Title}}", 13 | "termsOfService": "http://swagger.io/terms/", 14 | "contact": { 15 | "name": "API Support", 16 | "url": "http://www.swagger.io/support", 17 | "email": "support@swagger.io" 18 | }, 19 | "license": { 20 | "name": "Apache 2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 22 | }, 23 | "version": "{{.Version}}" 24 | }, 25 | "host": "{{.Host}}", 26 | "basePath": "{{.BasePath}}", 27 | "paths": { 28 | "/books": { 29 | "get": { 30 | "description": "get string by ID", 31 | "consumes": [ 32 | "application/json" 33 | ], 34 | "produces": [ 35 | "application/json" 36 | ], 37 | "summary": "Get a list of books in the the store", 38 | "responses": { 39 | "200": { 40 | "description": "ok", 41 | "schema": { 42 | "type": "array", 43 | "items": { 44 | "$ref": "#/definitions/v1.Book" 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | }, 52 | "definitions": { 53 | "v1.Book": { 54 | "type": "object", 55 | "properties": { 56 | "author": { 57 | "type": "string" 58 | }, 59 | "id": { 60 | "type": "integer" 61 | }, 62 | "title": { 63 | "type": "string" 64 | }, 65 | "year": { 66 | "type": "integer" 67 | } 68 | } 69 | } 70 | } 71 | }` 72 | 73 | // SwaggerInfov1 holds exported Swagger Info so clients can modify it 74 | var SwaggerInfov1 = &swag.Spec{ 75 | Version: "1.0", 76 | Host: "", 77 | BasePath: "/v1", 78 | Schemes: []string{}, 79 | Title: "Swagger Example API", 80 | Description: "This is a sample server.", 81 | InfoInstanceName: "v1", 82 | SwaggerTemplate: docTemplatev1, 83 | } 84 | 85 | func init() { 86 | swag.Register(SwaggerInfov1.InstanceName(), SwaggerInfov1) 87 | } 88 | -------------------------------------------------------------------------------- /example/multiple/docs/v1_swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "1.0" 17 | }, 18 | "basePath": "/v1", 19 | "paths": { 20 | "/books": { 21 | "get": { 22 | "description": "get string by ID", 23 | "consumes": [ 24 | "application/json" 25 | ], 26 | "produces": [ 27 | "application/json" 28 | ], 29 | "summary": "Get a list of books in the the store", 30 | "responses": { 31 | "200": { 32 | "description": "ok", 33 | "schema": { 34 | "type": "array", 35 | "items": { 36 | "$ref": "#/definitions/v1.Book" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | }, 44 | "definitions": { 45 | "v1.Book": { 46 | "type": "object", 47 | "properties": { 48 | "author": { 49 | "type": "string" 50 | }, 51 | "id": { 52 | "type": "integer" 53 | }, 54 | "title": { 55 | "type": "string" 56 | }, 57 | "year": { 58 | "type": "integer" 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /example/multiple/docs/v1_swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v1 2 | definitions: 3 | v1.Book: 4 | properties: 5 | author: 6 | type: string 7 | id: 8 | type: integer 9 | title: 10 | type: string 11 | year: 12 | type: integer 13 | type: object 14 | info: 15 | contact: 16 | email: support@swagger.io 17 | name: API Support 18 | url: http://www.swagger.io/support 19 | description: This is a sample server. 20 | license: 21 | name: Apache 2.0 22 | url: http://www.apache.org/licenses/LICENSE-2.0.html 23 | termsOfService: http://swagger.io/terms/ 24 | title: Swagger Example API 25 | version: "1.0" 26 | paths: 27 | /books: 28 | get: 29 | consumes: 30 | - application/json 31 | description: get string by ID 32 | produces: 33 | - application/json 34 | responses: 35 | "200": 36 | description: ok 37 | schema: 38 | items: 39 | $ref: '#/definitions/v1.Book' 40 | type: array 41 | summary: Get a list of books in the the store 42 | swagger: "2.0" 43 | -------------------------------------------------------------------------------- /example/multiple/docs/v2_docs.go: -------------------------------------------------------------------------------- 1 | // Package docs GENERATED BY SWAG; DO NOT EDIT 2 | // This file was generated by swaggo/swag 3 | package docs 4 | 5 | import "github.com/swaggo/swag" 6 | 7 | const docTemplatev2 = `{ 8 | "schemes": {{ marshal .Schemes }}, 9 | "swagger": "2.0", 10 | "info": { 11 | "description": "{{escape .Description}}", 12 | "title": "{{.Title}}", 13 | "termsOfService": "http://swagger.io/terms/", 14 | "contact": { 15 | "name": "API Support", 16 | "url": "http://www.swagger.io/support", 17 | "email": "support@swagger.io" 18 | }, 19 | "license": { 20 | "name": "Apache 2.0", 21 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 22 | }, 23 | "version": "{{.Version}}" 24 | }, 25 | "host": "{{.Host}}", 26 | "basePath": "{{.BasePath}}", 27 | "paths": { 28 | "/books": { 29 | "get": { 30 | "description": "get string by ID", 31 | "consumes": [ 32 | "application/json" 33 | ], 34 | "produces": [ 35 | "application/json" 36 | ], 37 | "summary": "Get a list of books in the the store", 38 | "responses": { 39 | "200": { 40 | "description": "ok", 41 | "schema": { 42 | "type": "array", 43 | "items": { 44 | "$ref": "#/definitions/v2.Book" 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | }, 52 | "definitions": { 53 | "v2.Book": { 54 | "type": "object", 55 | "properties": { 56 | "author": { 57 | "type": "string" 58 | }, 59 | "id": { 60 | "type": "integer" 61 | }, 62 | "title": { 63 | "type": "string" 64 | }, 65 | "year": { 66 | "type": "integer" 67 | } 68 | } 69 | } 70 | } 71 | }` 72 | 73 | // SwaggerInfov2 holds exported Swagger Info so clients can modify it 74 | var SwaggerInfov2 = &swag.Spec{ 75 | Version: "2.0", 76 | Host: "", 77 | BasePath: "/v2", 78 | Schemes: []string{}, 79 | Title: "Swagger Example API", 80 | Description: "This is a sample server.", 81 | InfoInstanceName: "v2", 82 | SwaggerTemplate: docTemplatev2, 83 | } 84 | 85 | func init() { 86 | swag.Register(SwaggerInfov2.InstanceName(), SwaggerInfov2) 87 | } 88 | -------------------------------------------------------------------------------- /example/multiple/docs/v2_swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "This is a sample server.", 5 | "title": "Swagger Example API", 6 | "termsOfService": "http://swagger.io/terms/", 7 | "contact": { 8 | "name": "API Support", 9 | "url": "http://www.swagger.io/support", 10 | "email": "support@swagger.io" 11 | }, 12 | "license": { 13 | "name": "Apache 2.0", 14 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 15 | }, 16 | "version": "2.0" 17 | }, 18 | "basePath": "/v2", 19 | "paths": { 20 | "/books": { 21 | "get": { 22 | "description": "get string by ID", 23 | "consumes": [ 24 | "application/json" 25 | ], 26 | "produces": [ 27 | "application/json" 28 | ], 29 | "summary": "Get a list of books in the the store", 30 | "responses": { 31 | "200": { 32 | "description": "ok", 33 | "schema": { 34 | "type": "array", 35 | "items": { 36 | "$ref": "#/definitions/v2.Book" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | }, 44 | "definitions": { 45 | "v2.Book": { 46 | "type": "object", 47 | "properties": { 48 | "author": { 49 | "type": "string" 50 | }, 51 | "id": { 52 | "type": "integer" 53 | }, 54 | "title": { 55 | "type": "string" 56 | }, 57 | "year": { 58 | "type": "integer" 59 | } 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /example/multiple/docs/v2_swagger.yaml: -------------------------------------------------------------------------------- 1 | basePath: /v2 2 | definitions: 3 | v2.Book: 4 | properties: 5 | author: 6 | type: string 7 | id: 8 | type: integer 9 | title: 10 | type: string 11 | year: 12 | type: integer 13 | type: object 14 | info: 15 | contact: 16 | email: support@swagger.io 17 | name: API Support 18 | url: http://www.swagger.io/support 19 | description: This is a sample server. 20 | license: 21 | name: Apache 2.0 22 | url: http://www.apache.org/licenses/LICENSE-2.0.html 23 | termsOfService: http://swagger.io/terms/ 24 | title: Swagger Example API 25 | version: "2.0" 26 | paths: 27 | /books: 28 | get: 29 | consumes: 30 | - application/json 31 | description: get string by ID 32 | produces: 33 | - application/json 34 | responses: 35 | "200": 36 | description: ok 37 | schema: 38 | items: 39 | $ref: '#/definitions/v2.Book' 40 | type: array 41 | summary: Get a list of books in the the store 42 | swagger: "2.0" 43 | -------------------------------------------------------------------------------- /example/multiple/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | swaggerFiles "github.com/swaggo/files" 6 | ginSwagger "github.com/swaggo/gin-swagger" 7 | v1 "github.com/swaggo/gin-swagger/example/multiple/api/v1" 8 | v2 "github.com/swaggo/gin-swagger/example/multiple/api/v2" 9 | _ "github.com/swaggo/gin-swagger/example/multiple/docs" 10 | ) 11 | 12 | func main() { 13 | // New gin router 14 | router := gin.New() 15 | 16 | // Register api/v1 endpoints 17 | v1.Register(router) 18 | router.GET("/swagger/v1/*any", ginSwagger.WrapHandler(swaggerFiles.NewHandler(), ginSwagger.InstanceName("v1"))) 19 | 20 | // Register api/v2 endpoints 21 | v2.Register(router) 22 | router.GET("/swagger/v2/*any", ginSwagger.WrapHandler(swaggerFiles.NewHandler(), ginSwagger.InstanceName("v2"))) 23 | 24 | // Listen and Server in 25 | _ = router.Run() 26 | } 27 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/swaggo/gin-swagger 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gin-contrib/gzip v0.0.6 7 | github.com/gin-gonic/gin v1.9.0 8 | github.com/stretchr/testify v1.8.1 9 | github.com/swaggo/files v1.0.1 10 | github.com/swaggo/swag v1.8.12 11 | golang.org/x/net v0.8.0 12 | ) 13 | 14 | require ( 15 | github.com/KyleBanks/depth v1.2.1 // indirect 16 | github.com/PuerkitoBio/purell v1.1.1 // indirect 17 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 18 | github.com/bytedance/sonic v1.8.0 // indirect 19 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 20 | github.com/davecgh/go-spew v1.1.1 // indirect 21 | github.com/gin-contrib/sse v0.1.0 // indirect 22 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 23 | github.com/go-openapi/jsonreference v0.19.6 // indirect 24 | github.com/go-openapi/spec v0.20.4 // indirect 25 | github.com/go-openapi/swag v0.19.15 // indirect 26 | github.com/go-playground/locales v0.14.1 // indirect 27 | github.com/go-playground/universal-translator v0.18.1 // indirect 28 | github.com/go-playground/validator/v10 v10.11.2 // indirect 29 | github.com/goccy/go-json v0.10.0 // indirect 30 | github.com/josharian/intern v1.0.0 // indirect 31 | github.com/json-iterator/go v1.1.12 // indirect 32 | github.com/klauspost/cpuid/v2 v2.0.9 // indirect 33 | github.com/leodido/go-urn v1.2.1 // indirect 34 | github.com/mailru/easyjson v0.7.6 // indirect 35 | github.com/mattn/go-isatty v0.0.17 // indirect 36 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 37 | github.com/modern-go/reflect2 v1.0.2 // indirect 38 | github.com/pelletier/go-toml/v2 v2.0.6 // indirect 39 | github.com/pmezard/go-difflib v1.0.0 // indirect 40 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 41 | github.com/ugorji/go/codec v1.2.9 // indirect 42 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect 43 | golang.org/x/crypto v0.5.0 // indirect 44 | golang.org/x/sys v0.6.0 // indirect 45 | golang.org/x/text v0.8.0 // indirect 46 | golang.org/x/tools v0.7.0 // indirect 47 | google.golang.org/protobuf v1.28.1 // indirect 48 | gopkg.in/yaml.v2 v2.4.0 // indirect 49 | gopkg.in/yaml.v3 v3.0.1 // indirect 50 | ) 51 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= 3 | github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= 4 | github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= 5 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 6 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= 7 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 8 | github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= 9 | github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= 10 | github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= 11 | github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= 12 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= 13 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= 14 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 15 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 16 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 17 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 18 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 19 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 20 | github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= 21 | github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= 22 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 23 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 24 | github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= 25 | github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= 26 | github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= 27 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 28 | github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= 29 | github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 30 | github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= 31 | github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= 32 | github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= 33 | github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= 34 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 35 | github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= 36 | github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= 37 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 38 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 39 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 40 | github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= 41 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 42 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 43 | github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= 44 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 45 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 46 | github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= 47 | github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= 48 | github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= 49 | github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 50 | github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= 51 | github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 52 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 53 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 54 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 55 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 56 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 57 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 58 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 59 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 60 | github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= 61 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 62 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 63 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 64 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 65 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 66 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 67 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 68 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 69 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 70 | github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= 71 | github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 72 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 73 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 74 | github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= 75 | github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 76 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 77 | github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= 78 | github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 79 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 80 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 81 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 82 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 83 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 84 | github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= 85 | github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= 86 | github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= 87 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 88 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 89 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 90 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 91 | github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= 92 | github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= 93 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 94 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 95 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 96 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 97 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 98 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 99 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 100 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 101 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 102 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 103 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 104 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 105 | github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= 106 | github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= 107 | github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= 108 | github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its= 109 | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= 110 | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 111 | github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= 112 | github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= 113 | github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= 114 | github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= 115 | github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 116 | github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= 117 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 118 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= 119 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 120 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 121 | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 122 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 123 | golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= 124 | golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= 125 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 126 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 127 | golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= 128 | golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 129 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 130 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 131 | golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= 132 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 133 | golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= 134 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 135 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 136 | golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= 137 | golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 138 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 139 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 140 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 141 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 142 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 143 | golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 144 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 145 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 146 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 147 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 148 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 149 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 150 | golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 151 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 152 | golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= 153 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 154 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 155 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 156 | golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= 157 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 158 | golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 159 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 160 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 161 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 162 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 163 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 164 | golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 165 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 166 | golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= 167 | golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 168 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 169 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 170 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 171 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 172 | golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= 173 | golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= 174 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 175 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 176 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 177 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 178 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 179 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 180 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 181 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 182 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 183 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 184 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 185 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 186 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 187 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 188 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 189 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 190 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 191 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 192 | gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 193 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 194 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 195 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 196 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 197 | -------------------------------------------------------------------------------- /swagger.go: -------------------------------------------------------------------------------- 1 | package ginSwagger 2 | 3 | import ( 4 | htmlTemplate "html/template" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | "regexp" 9 | "sync" 10 | textTemplate "text/template" 11 | 12 | "golang.org/x/net/webdav" 13 | 14 | "github.com/gin-gonic/gin" 15 | "github.com/swaggo/swag" 16 | ) 17 | 18 | type swaggerConfig struct { 19 | URL string 20 | DocExpansion string 21 | Title string 22 | Oauth2RedirectURL htmlTemplate.JS 23 | DefaultModelsExpandDepth int 24 | DeepLinking bool 25 | PersistAuthorization bool 26 | Oauth2DefaultClientID string 27 | Oauth2UsePkce bool 28 | } 29 | 30 | // Config stores ginSwagger configuration variables. 31 | type Config struct { 32 | // The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `doc.json`. 33 | URL string 34 | DocExpansion string 35 | InstanceName string 36 | Title string 37 | DefaultModelsExpandDepth int 38 | DeepLinking bool 39 | PersistAuthorization bool 40 | Oauth2DefaultClientID string 41 | Oauth2UsePkce bool 42 | } 43 | 44 | func (config Config) toSwaggerConfig() swaggerConfig { 45 | return swaggerConfig{ 46 | URL: config.URL, 47 | DeepLinking: config.DeepLinking, 48 | DocExpansion: config.DocExpansion, 49 | DefaultModelsExpandDepth: config.DefaultModelsExpandDepth, 50 | Oauth2RedirectURL: "`${window.location.protocol}//${window.location.host}$" + 51 | "{window.location.pathname.split('/').slice(0, window.location.pathname.split('/').length - 1).join('/')}" + 52 | "/oauth2-redirect.html`", 53 | Title: config.Title, 54 | PersistAuthorization: config.PersistAuthorization, 55 | Oauth2DefaultClientID: config.Oauth2DefaultClientID, 56 | Oauth2UsePkce: config.Oauth2UsePkce, 57 | } 58 | } 59 | 60 | // URL presents the url pointing to API definition (normally swagger.json or swagger.yaml). 61 | func URL(url string) func(*Config) { 62 | return func(c *Config) { 63 | c.URL = url 64 | } 65 | } 66 | 67 | // DocExpansion list, full, none. 68 | func DocExpansion(docExpansion string) func(*Config) { 69 | return func(c *Config) { 70 | c.DocExpansion = docExpansion 71 | } 72 | } 73 | 74 | // DeepLinking set the swagger deep linking configuration. 75 | func DeepLinking(deepLinking bool) func(*Config) { 76 | return func(c *Config) { 77 | c.DeepLinking = deepLinking 78 | } 79 | } 80 | 81 | // DefaultModelsExpandDepth set the default expansion depth for models 82 | // (set to -1 completely hide the models). 83 | func DefaultModelsExpandDepth(depth int) func(*Config) { 84 | return func(c *Config) { 85 | c.DefaultModelsExpandDepth = depth 86 | } 87 | } 88 | 89 | // InstanceName set the instance name that was used to generate the swagger documents 90 | // Defaults to swag.Name ("swagger"). 91 | func InstanceName(name string) func(*Config) { 92 | return func(c *Config) { 93 | c.InstanceName = name 94 | } 95 | } 96 | 97 | // PersistAuthorization Persist authorization information over browser close/refresh. 98 | // Defaults to false. 99 | func PersistAuthorization(persistAuthorization bool) func(*Config) { 100 | return func(c *Config) { 101 | c.PersistAuthorization = persistAuthorization 102 | } 103 | } 104 | 105 | // Oauth2DefaultClientID set the default client ID used for OAuth2 106 | func Oauth2DefaultClientID(oauth2DefaultClientID string) func(*Config) { 107 | return func(c *Config) { 108 | c.Oauth2DefaultClientID = oauth2DefaultClientID 109 | } 110 | } 111 | 112 | // Oauth2UsePkce enables Proof Key for Code Exchange. 113 | // Corresponds to the usePkceWithAuthorizationCodeGrant property of the Swagger UI 114 | // and applies only to accessCode (Authorization Code) flows. 115 | func Oauth2UsePkce(usePkce bool) func(*Config) { 116 | return func(c *Config) { 117 | c.Oauth2UsePkce = usePkce 118 | } 119 | } 120 | 121 | // WrapHandler wraps `http.Handler` into `gin.HandlerFunc`. 122 | func WrapHandler(handler *webdav.Handler, options ...func(*Config)) gin.HandlerFunc { 123 | var config = Config{ 124 | URL: "doc.json", 125 | DocExpansion: "list", 126 | InstanceName: swag.Name, 127 | Title: "Swagger UI", 128 | DefaultModelsExpandDepth: 1, 129 | DeepLinking: true, 130 | PersistAuthorization: false, 131 | Oauth2DefaultClientID: "", 132 | Oauth2UsePkce: false, 133 | } 134 | 135 | for _, c := range options { 136 | c(&config) 137 | } 138 | 139 | return CustomWrapHandler(&config, handler) 140 | } 141 | 142 | // CustomWrapHandler wraps `http.Handler` into `gin.HandlerFunc`. 143 | func CustomWrapHandler(config *Config, handler *webdav.Handler) gin.HandlerFunc { 144 | var once sync.Once 145 | 146 | if config.InstanceName == "" { 147 | config.InstanceName = swag.Name 148 | } 149 | 150 | if config.Title == "" { 151 | config.Title = "Swagger UI" 152 | } 153 | 154 | // create a template with name 155 | index, _ := htmlTemplate.New("swagger_index.html").Parse(swaggerIndexTpl) 156 | js, _ := textTemplate.New("swagger_index.js").Parse(swaggerJSTpl) 157 | css, _ := textTemplate.New("swagger_index.css").Parse(swaggerStyleTpl) 158 | 159 | var matcher = regexp.MustCompile(`(.*)(index\.html|index\.css|swagger-initializer\.js|doc\.json|favicon-16x16\.png|favicon-32x32\.png|/oauth2-redirect\.html|swagger-ui\.css|swagger-ui\.css\.map|swagger-ui\.js|swagger-ui\.js\.map|swagger-ui-bundle\.js|swagger-ui-bundle\.js\.map|swagger-ui-standalone-preset\.js|swagger-ui-standalone-preset\.js\.map)[?|.]*`) 160 | 161 | return func(ctx *gin.Context) { 162 | if ctx.Request.Method != http.MethodGet { 163 | ctx.AbortWithStatus(http.StatusMethodNotAllowed) 164 | 165 | return 166 | } 167 | 168 | matches := matcher.FindStringSubmatch(ctx.Request.RequestURI) 169 | 170 | if len(matches) != 3 { 171 | ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) 172 | 173 | return 174 | } 175 | 176 | path := matches[2] 177 | once.Do(func() { 178 | handler.Prefix = matches[1] 179 | }) 180 | 181 | switch filepath.Ext(path) { 182 | case ".html": 183 | ctx.Header("Content-Type", "text/html; charset=utf-8") 184 | case ".css": 185 | ctx.Header("Content-Type", "text/css; charset=utf-8") 186 | case ".js": 187 | ctx.Header("Content-Type", "application/javascript") 188 | case ".png": 189 | ctx.Header("Content-Type", "image/png") 190 | case ".json": 191 | ctx.Header("Content-Type", "application/json; charset=utf-8") 192 | } 193 | 194 | switch path { 195 | case "index.html": 196 | _ = index.Execute(ctx.Writer, config.toSwaggerConfig()) 197 | case "index.css": 198 | _ = css.Execute(ctx.Writer, config.toSwaggerConfig()) 199 | case "swagger-initializer.js": 200 | _ = js.Execute(ctx.Writer, config.toSwaggerConfig()) 201 | case "doc.json": 202 | doc, err := swag.ReadDoc(config.InstanceName) 203 | if err != nil { 204 | ctx.AbortWithStatus(http.StatusInternalServerError) 205 | 206 | return 207 | } 208 | 209 | ctx.String(http.StatusOK, doc) 210 | default: 211 | handler.ServeHTTP(ctx.Writer, ctx.Request) 212 | } 213 | } 214 | } 215 | 216 | // DisablingWrapHandler turn handler off 217 | // if specified environment variable passed. 218 | func DisablingWrapHandler(handler *webdav.Handler, envName string) gin.HandlerFunc { 219 | if os.Getenv(envName) != "" { 220 | return func(c *gin.Context) { 221 | // Simulate behavior when route unspecified and 222 | // return 404 HTTP code 223 | c.String(http.StatusNotFound, "") 224 | } 225 | } 226 | 227 | return WrapHandler(handler) 228 | } 229 | 230 | // DisablingCustomWrapHandler turn handler off 231 | // if specified environment variable passed. 232 | func DisablingCustomWrapHandler(config *Config, handler *webdav.Handler, envName string) gin.HandlerFunc { 233 | if os.Getenv(envName) != "" { 234 | return func(c *gin.Context) { 235 | // Simulate behavior when route unspecified and 236 | // return 404 HTTP code 237 | c.String(http.StatusNotFound, "") 238 | } 239 | } 240 | 241 | return CustomWrapHandler(config, handler) 242 | } 243 | 244 | const swaggerStyleTpl = ` 245 | html 246 | { 247 | box-sizing: border-box; 248 | overflow: -moz-scrollbars-vertical; 249 | overflow-y: scroll; 250 | } 251 | *, 252 | *:before, 253 | *:after 254 | { 255 | box-sizing: inherit; 256 | } 257 | 258 | body { 259 | margin:0; 260 | background: #fafafa; 261 | } 262 | ` 263 | 264 | const swaggerJSTpl = ` 265 | window.onload = function() { 266 | // Build a system 267 | const ui = SwaggerUIBundle({ 268 | url: "{{.URL}}", 269 | dom_id: '#swagger-ui', 270 | validatorUrl: null, 271 | oauth2RedirectUrl: {{.Oauth2RedirectURL}}, 272 | persistAuthorization: {{.PersistAuthorization}}, 273 | presets: [ 274 | SwaggerUIBundle.presets.apis, 275 | SwaggerUIStandalonePreset 276 | ], 277 | plugins: [ 278 | SwaggerUIBundle.plugins.DownloadUrl 279 | ], 280 | layout: "StandaloneLayout", 281 | docExpansion: "{{.DocExpansion}}", 282 | deepLinking: {{.DeepLinking}}, 283 | defaultModelsExpandDepth: {{.DefaultModelsExpandDepth}} 284 | }) 285 | 286 | const defaultClientId = "{{.Oauth2DefaultClientID}}"; 287 | if (defaultClientId) { 288 | ui.initOAuth({ 289 | clientId: defaultClientId, 290 | usePkceWithAuthorizationCodeGrant: {{.Oauth2UsePkce}} 291 | }) 292 | } 293 | 294 | window.ui = ui 295 | } 296 | ` 297 | 298 | const swaggerIndexTpl = ` 299 | 300 | 301 |
302 | 303 |