diff --git a/echo_v3/example/docs/docs.go b/echo_v3/example/docs/docs.go
new file mode 100644
index 0000000..d783604
--- /dev/null
+++ b/echo_v3/example/docs/docs.go
@@ -0,0 +1,45 @@
+// Package docs Code generated by swaggo/swag. DO NOT EDIT
+package docs
+
+import "github.com/swaggo/swag"
+
+const docTemplate = `{
+ "schemes": {{ marshal .Schemes }},
+ "swagger": "2.0",
+ "info": {
+ "description": "{{escape .Description}}",
+ "title": "{{.Title}}",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "http://www.swagger.io/support",
+ "email": "support@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "{{.Version}}"
+ },
+ "host": "{{.Host}}",
+ "basePath": "{{.BasePath}}",
+ "paths": {}
+}`
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = &swag.Spec{
+ Version: "1.0",
+ Host: "petstore.swagger.io",
+ BasePath: "/v2",
+ Schemes: []string{},
+ Title: "Swagger Example API With Echo V3",
+ Description: "This is a sample server Petstore server.",
+ InfoInstanceName: "swagger",
+ SwaggerTemplate: docTemplate,
+ LeftDelim: "{{",
+ RightDelim: "}}",
+}
+
+func init() {
+ swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
+}
diff --git a/echo_v3/example/docs/swagger.json b/echo_v3/example/docs/swagger.json
new file mode 100644
index 0000000..e3dd377
--- /dev/null
+++ b/echo_v3/example/docs/swagger.json
@@ -0,0 +1,21 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "description": "This is a sample server Petstore server.",
+ "title": "Swagger Example API With Echo V3",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "http://www.swagger.io/support",
+ "email": "support@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "1.0"
+ },
+ "host": "petstore.swagger.io",
+ "basePath": "/v2",
+ "paths": {}
+}
\ No newline at end of file
diff --git a/echo_v3/example/docs/swagger.yaml b/echo_v3/example/docs/swagger.yaml
new file mode 100644
index 0000000..820fc7a
--- /dev/null
+++ b/echo_v3/example/docs/swagger.yaml
@@ -0,0 +1,16 @@
+basePath: /v2
+host: petstore.swagger.io
+info:
+ contact:
+ email: support@swagger.io
+ name: API Support
+ url: http://www.swagger.io/support
+ description: This is a sample server Petstore server.
+ license:
+ name: Apache 2.0
+ url: http://www.apache.org/licenses/LICENSE-2.0.html
+ termsOfService: http://swagger.io/terms/
+ title: Swagger Example API With Echo V3
+ version: "1.0"
+paths: {}
+swagger: "2.0"
diff --git a/echo_v3/example/main.go b/echo_v3/example/main.go
new file mode 100644
index 0000000..81c18ba
--- /dev/null
+++ b/echo_v3/example/main.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "github.com/labstack/echo"
+ "github.com/swaggo/echo-swagger/echo_v3"
+ _ "github.com/swaggo/echo-swagger/example/docs" // docs is generated by Swag CLI, you have to import it.
+)
+
+// @title Swagger Example API With Echo V3
+// @version 1.0
+// @description This is a sample server Petstore server.
+// @termsOfService http://swagger.io/terms/
+
+// @contact.name API Support
+// @contact.url http://www.swagger.io/support
+// @contact.email support@swagger.io
+
+// @license.name Apache 2.0
+// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
+
+// @host petstore.swagger.io
+// @BasePath /v2
+func main() {
+ e := echo.New()
+
+ e.GET("/swagger/*", echo_v3.WrapHandler)
+
+ /*
+ Or can use EchoWrapHandler func with configurations.
+ url := echoSwagger.URL("http://localhost:1323/swagger/doc.json") //The url pointing to API definition
+ e.GET("/swagger/*", echoSwagger.EchoWrapHandler(url))
+ */
+ e.Logger.Fatal(e.Start(":1323"))
+}
diff --git a/echo_v3/swagger_echo_v3.go b/echo_v3/swagger_echo_v3.go
new file mode 100644
index 0000000..c27e853
--- /dev/null
+++ b/echo_v3/swagger_echo_v3.go
@@ -0,0 +1,311 @@
+package echo_v3
+
+import (
+ "html/template"
+ "net/http"
+ "path/filepath"
+ "regexp"
+
+ "github.com/ghodss/yaml"
+ "github.com/labstack/echo"
+ swaggerFiles "github.com/swaggo/files/v2"
+ "github.com/swaggo/swag"
+)
+
+// Config stores echoSwagger configuration variables.
+type Config struct {
+ // The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `mockedSwag.json`.
+ URLs []string
+ DocExpansion string
+ DomID string
+ InstanceName string
+ DeepLinking bool
+ PersistAuthorization bool
+ SyntaxHighlight bool
+
+ // The information for OAuth2 integration, if any.
+ OAuth *OAuthConfig
+}
+
+// OAuthConfig stores configuration for Swagger UI OAuth2 integration. See
+// https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/ for further details.
+type OAuthConfig struct {
+ // The ID of the client sent to the OAuth2 IAM provider.
+ ClientId string
+
+ // The OAuth2 realm that the client should operate in. If not applicable, use empty string.
+ Realm string
+
+ // The name to display for the application in the authentication popup.
+ AppName string
+}
+
+// URL presents the url pointing to API definition (normally swagger.json or swagger.yaml).
+func URL(url string) func(*Config) {
+ return func(c *Config) {
+ c.URLs = append(c.URLs, url)
+ }
+}
+
+// DeepLinking true, false.
+func DeepLinking(deepLinking bool) func(*Config) {
+ return func(c *Config) {
+ c.DeepLinking = deepLinking
+ }
+}
+
+// SyntaxHighlight true, false.
+func SyntaxHighlight(syntaxHighlight bool) func(*Config) {
+ return func(c *Config) {
+ c.SyntaxHighlight = syntaxHighlight
+ }
+}
+
+// DocExpansion list, full, none.
+func DocExpansion(docExpansion string) func(*Config) {
+ return func(c *Config) {
+ c.DocExpansion = docExpansion
+ }
+}
+
+// DomID #swagger-ui.
+func DomID(domID string) func(*Config) {
+ return func(c *Config) {
+ c.DomID = domID
+ }
+}
+
+// InstanceName specified swag instance name.
+func InstanceName(instanceName string) func(*Config) {
+ return func(c *Config) {
+ c.InstanceName = instanceName
+ }
+}
+
+// PersistAuthorization Persist authorization information over browser close/refresh.
+// Defaults to false.
+func PersistAuthorization(persistAuthorization bool) func(*Config) {
+ return func(c *Config) {
+ c.PersistAuthorization = persistAuthorization
+ }
+}
+
+func OAuth(config *OAuthConfig) func(*Config) {
+ return func(c *Config) {
+ c.OAuth = config
+ }
+}
+
+func newConfig(configFns ...func(*Config)) *Config {
+ config := Config{
+ URLs: []string{"doc.json", "doc.yaml"},
+ DocExpansion: "list",
+ DomID: "swagger-ui",
+ InstanceName: "swagger",
+ DeepLinking: true,
+ PersistAuthorization: false,
+ SyntaxHighlight: true,
+ }
+
+ for _, fn := range configFns {
+ fn(&config)
+ }
+
+ if config.InstanceName == "" {
+ config.InstanceName = swag.Name
+ }
+
+ return &config
+}
+
+// WrapHandler wraps swaggerFiles.Handler and returns echo.HandlerFunc
+var WrapHandler = EchoWrapHandler()
+
+// EchoWrapHandler wraps `http.Handler` into `echo.HandlerFunc`.
+func EchoWrapHandler(options ...func(*Config)) echo.HandlerFunc {
+ config := newConfig(options...)
+
+ // create a template with name
+ index, _ := template.New("swagger_index.html").Parse(indexTemplate)
+
+ var re = regexp.MustCompile(`^(.*/)([^?].*)?[?|.]*$`)
+
+ return func(c echo.Context) error {
+ if c.Request().Method != http.MethodGet {
+ return echo.NewHTTPError(http.StatusMethodNotAllowed, http.StatusText(http.StatusMethodNotAllowed))
+ }
+
+ matches := re.FindStringSubmatch(c.Request().RequestURI)
+ path := matches[2]
+
+ switch filepath.Ext(path) {
+ case ".html":
+ c.Response().Header().Set("Content-Type", "text/html; charset=utf-8")
+ case ".css":
+ c.Response().Header().Set("Content-Type", "text/css; charset=utf-8")
+ case ".js":
+ c.Response().Header().Set("Content-Type", "application/javascript")
+ case ".json":
+ c.Response().Header().Set("Content-Type", "application/json; charset=utf-8")
+ case ".yaml":
+ c.Response().Header().Set("Content-Type", "text/plain; charset=utf-8")
+ case ".png":
+ c.Response().Header().Set("Content-Type", "image/png")
+ }
+
+ response := c.Response()
+ // This check fixes an error introduced here: https://github.com/labstack/echo/blob/8da8e161380fd926d4341721f0328f1e94d6d0a2/response.go#L86-L88
+ if _, ok := response.Writer.(http.Flusher); ok {
+ defer response.Flush()
+ }
+
+ switch path {
+ case "":
+ _ = c.Redirect(http.StatusMovedPermanently, matches[1]+"/"+"index.html")
+ case "index.html":
+ _ = index.Execute(c.Response().Writer, config)
+ case "doc.json":
+ doc, err := swag.ReadDoc(config.InstanceName)
+ if err != nil {
+ c.Error(err)
+
+ return nil
+ }
+
+ _, _ = c.Response().Writer.Write([]byte(doc))
+ case "doc.yaml":
+ jsonString, err := swag.ReadDoc(config.InstanceName)
+ if err != nil {
+ c.Error(err)
+
+ return nil
+ }
+ doc, err := yaml.JSONToYAML([]byte(jsonString))
+ if err != nil {
+ c.Error(err)
+
+ return nil
+ }
+ _, _ = c.Response().Writer.Write(doc)
+ default:
+ c.Request().URL.Path = matches[2]
+ http.FileServer(http.FS(swaggerFiles.FS)).ServeHTTP(c.Response(), c.Request())
+ }
+
+ return nil
+ }
+}
+
+const indexTemplate = `
+
+
+
+
+ Swagger UI
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`
diff --git a/echo_v3/swagger_echo_v3_test.go b/echo_v3/swagger_echo_v3_test.go
new file mode 100644
index 0000000..b18cf58
--- /dev/null
+++ b/echo_v3/swagger_echo_v3_test.go
@@ -0,0 +1,434 @@
+package echo_v3
+
+import (
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/labstack/echo"
+ "github.com/stretchr/testify/assert"
+ "github.com/swaggo/swag"
+)
+
+type mockedSwag struct{}
+
+func (s *mockedSwag) ReadDoc() string {
+ return `{
+ "swagger": "2.0",
+ "info": {
+ "description": "This is a sample server Petstore server.",
+ "title": "Swagger Example API",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "name": "API Support",
+ "url": "http://www.swagger.io/support",
+ "email": "support@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "1.0"
+ },
+ "host": "petstore.swagger.io",
+ "basePath": "/v2",
+ "paths": {
+ "/file/upload": {
+ "post": {
+ "description": "Upload file",
+ "consumes": [
+ "multipart/form-data"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "summary": "Upload file",
+ "operationId": "file.upload",
+ "parameters": [
+ {
+ "type": "file",
+ "description": "this is a test file",
+ "name": "file",
+ "in": "formData",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "ok",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "We need ID!!",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ },
+ "404": {
+ "description": "Can not find ID",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ }
+ }
+ }
+ },
+ "/testapi/get-string-by-int/{some_id}": {
+ "get": {
+ "description": "get string by ID",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "summary": "Add a new pet to the store",
+ "operationId": "get-string-by-int",
+ "parameters": [
+ {
+ "type": "int",
+ "description": "Some ID",
+ "name": "some_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "Some ID",
+ "name": "some_id",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.Pet"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "ok",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "We need ID!!",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ },
+ "404": {
+ "description": "Can not find ID",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ }
+ }
+ }
+ },
+ "/testapi/get-struct-array-by-string/{some_id}": {
+ "get": {
+ "description": "get struct array by ID",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "operationId": "get-struct-array-by-string",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Some ID",
+ "name": "some_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "int",
+ "description": "Offset",
+ "name": "offset",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "int",
+ "description": "Offset",
+ "name": "limit",
+ "in": "query",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "ok",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "400": {
+ "description": "We need ID!!",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ },
+ "404": {
+ "description": "Can not find ID",
+ "schema": {
+ "type": "object",
+ "$ref": "#/definitions/web.APIError"
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "web.APIError": {
+ "type": "object",
+ "properties": {
+ "CreatedAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "ErrorCode": {
+ "type": "integer"
+ },
+ "ErrorMessage": {
+ "type": "string"
+ }
+ }
+ },
+ "web.Pet": {
+ "type": "object",
+ "properties": {
+ "Category": {
+ "type": "object"
+ },
+ "ID": {
+ "type": "integer"
+ },
+ "Name": {
+ "type": "string"
+ },
+ "PhotoUrls": {
+ "type": "array"
+ },
+ "Status": {
+ "type": "string"
+ },
+ "Tags": {
+ "type": "array"
+ }
+ }
+ }
+ }
+}`
+}
+
+func TestWrapHandler(t *testing.T) {
+ router := echo.New()
+
+ router.Any("/*", EchoWrapHandler(DocExpansion("none"), DomID("swagger-ui")))
+
+ w1 := performRequest(http.MethodGet, "/index.html", router)
+ assert.Equal(t, http.StatusOK, w1.Code)
+ assert.Equal(t, w1.Header()["Content-Type"][0], "text/html; charset=utf-8")
+
+ assert.Equal(t, http.StatusInternalServerError, performRequest(http.MethodGet, "/doc.json", router).Code)
+
+ doc := &mockedSwag{}
+ swag.Register(swag.Name, doc)
+ w2 := performRequest(http.MethodGet, "/doc.json", router)
+ assert.Equal(t, http.StatusOK, w2.Code)
+ assert.Equal(t, w2.Header()["Content-Type"][0], "application/json; charset=utf-8")
+
+ // Perform body rendering validation
+ w2Body, err := ioutil.ReadAll(w2.Body)
+ assert.NoError(t, err)
+ assert.Equal(t, doc.ReadDoc(), string(w2Body))
+
+ w3 := performRequest(http.MethodGet, "/favicon-16x16.png", router)
+ assert.Equal(t, http.StatusOK, w3.Code)
+ assert.Equal(t, w3.Header()["Content-Type"][0], "image/png")
+
+ w4 := performRequest(http.MethodGet, "/swagger-ui.css", router)
+ assert.Equal(t, http.StatusOK, w4.Code)
+ assert.Equal(t, w4.Header()["Content-Type"][0], "text/css; charset=utf-8")
+
+ w5 := performRequest(http.MethodGet, "/swagger-ui-bundle.js", router)
+ assert.Equal(t, http.StatusOK, w5.Code)
+ assert.Equal(t, w5.Header()["Content-Type"][0], "application/javascript")
+
+ assert.Equal(t, http.StatusNotFound, performRequest(http.MethodGet, "/notfound", router).Code)
+
+ assert.Equal(t, http.StatusMovedPermanently, performRequest(http.MethodGet, "/", router).Code)
+
+ assert.Equal(t, http.StatusMethodNotAllowed, performRequest(http.MethodPost, "/index.html", router).Code)
+
+ assert.Equal(t, http.StatusMethodNotAllowed, performRequest(http.MethodPut, "/index.html", router).Code)
+
+}
+
+func TestConfig(t *testing.T) {
+ router := echo.New()
+
+ swaggerHandler := URL("swagger.json")
+ router.Any("/*", EchoWrapHandler(swaggerHandler))
+
+ w := performRequest("GET", "/index.html", router)
+ assert.Equal(t, 200, w.Code)
+ assert.Contains(t, w.Body.String(), `url: "swagger.json"`)
+}
+
+func TestConfigWithOAuth(t *testing.T) {
+ router := echo.New()
+
+ swaggerHandler := EchoWrapHandler(OAuth(&OAuthConfig{
+ ClientId: "my-client-id",
+ Realm: "my-realm",
+ AppName: "My App Name",
+ }))
+ router.GET("/*", swaggerHandler)
+
+ w := performRequest("GET", "/index.html", router)
+ assert.Equal(t, 200, w.Code)
+ body := w.Body.String()
+ assert.Contains(t, body, `ui.initOAuth({
+ clientId: "my-client-id",
+ realm: "my-realm",
+ appName: "My App Name"
+ })`)
+}
+
+func TestHandlerReuse(t *testing.T) {
+ router := echo.New()
+
+ router.GET("/swagger/*", EchoWrapHandler())
+ router.GET("/admin/swagger/*", EchoWrapHandler())
+
+ w1 := performRequest(http.MethodGet, "/swagger/index.html", router)
+ assert.Equal(t, http.StatusOK, w1.Code)
+ assert.Equal(t, w1.Header()["Content-Type"][0], "text/html; charset=utf-8")
+
+ w2 := performRequest(http.MethodGet, "/admin/swagger/index.html", router)
+ assert.Equal(t, http.StatusOK, w2.Code)
+ assert.Equal(t, w2.Header()["Content-Type"][0], "text/html; charset=utf-8")
+
+ w3 := performRequest(http.MethodGet, "/swagger/index.html", router)
+ assert.Equal(t, http.StatusOK, w3.Code)
+ assert.Equal(t, w3.Header()["Content-Type"][0], "text/html; charset=utf-8")
+
+ w4 := performRequest(http.MethodGet, "/admin/swagger/index.html", router)
+ assert.Equal(t, http.StatusOK, w4.Code)
+ assert.Equal(t, w4.Header()["Content-Type"][0], "text/html; charset=utf-8")
+}
+
+type httpWriter struct{}
+
+func (h httpWriter) Header() http.Header {
+ return http.Header{}
+}
+
+func (h httpWriter) Write(bytes []byte) (int, error) {
+ return len(bytes), nil
+}
+
+func (h httpWriter) WriteHeader(_ int) {}
+
+func TestMissingFlusher(t *testing.T) {
+ router := echo.New()
+
+ router.GET("/swagger/*", EchoWrapHandler())
+
+ r := httptest.NewRequest(http.MethodGet, "/swagger/index.html", nil)
+ router.ServeHTTP(httpWriter{}, r)
+}
+
+func performRequest(method, target string, e http.Handler) *httptest.ResponseRecorder {
+ r := httptest.NewRequest(method, target, nil)
+ w := httptest.NewRecorder()
+
+ e.ServeHTTP(w, r)
+ return w
+}
+
+func TestURL(t *testing.T) {
+ var cfg Config
+ expected := "https://github.com/swaggo/http-swagger"
+ URL(expected)(&cfg)
+ assert.Equal(t, expected, cfg.URLs[0])
+}
+
+func TestDeepLinking(t *testing.T) {
+ var cfg Config
+ expected := true
+ DeepLinking(expected)(&cfg)
+ assert.Equal(t, expected, cfg.DeepLinking)
+}
+
+func TestSyntaxHighlight(t *testing.T) {
+ var cfg Config
+ expected := true
+ SyntaxHighlight(expected)(&cfg)
+ assert.Equal(t, expected, cfg.SyntaxHighlight)
+}
+
+func TestDocExpansion(t *testing.T) {
+ var cfg Config
+ expected := "https://github.com/swaggo/docs"
+ DocExpansion(expected)(&cfg)
+ assert.Equal(t, expected, cfg.DocExpansion)
+}
+
+func TestDomID(t *testing.T) {
+ var cfg Config
+ expected := "swagger-ui"
+ DomID(expected)(&cfg)
+ assert.Equal(t, expected, cfg.DomID)
+}
+
+func TestInstanceName(t *testing.T) {
+ var cfg Config
+
+ expected := "custom-instance-name"
+ InstanceName(expected)(&cfg)
+ assert.Equal(t, expected, cfg.InstanceName)
+
+ newCfg := newConfig(InstanceName(""))
+ assert.Equal(t, swag.Name, newCfg.InstanceName)
+}
+
+func TestPersistAuthorization(t *testing.T) {
+ var cfg Config
+ expected := true
+ PersistAuthorization(expected)(&cfg)
+ assert.Equal(t, expected, cfg.PersistAuthorization)
+}
+
+func TestOAuth(t *testing.T) {
+ var cfg Config
+ expected := OAuthConfig{
+ ClientId: "my-client-id",
+ Realm: "my-realm",
+ AppName: "My App Name",
+ }
+ OAuth(&expected)(&cfg)
+ assert.Equal(t, expected.ClientId, cfg.OAuth.ClientId)
+ assert.Equal(t, expected.Realm, cfg.OAuth.Realm)
+ assert.Equal(t, expected.AppName, cfg.OAuth.AppName)
+}
+
+func TestOAuthNil(t *testing.T) {
+ var cfg Config
+ var expected *OAuthConfig
+ OAuth(expected)(&cfg)
+ assert.Equal(t, expected, cfg.OAuth)
+}
diff --git a/go.mod b/go.mod
index 1b50ec8..98a86f9 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,9 @@ go 1.17
require (
github.com/ghodss/yaml v1.0.0
+ github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/echo/v4 v4.9.0
- github.com/stretchr/testify v1.7.0
+ github.com/stretchr/testify v1.8.4
github.com/swaggo/files/v2 v2.0.0
github.com/swaggo/swag v1.8.12
)
@@ -20,18 +21,18 @@ require (
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/josharian/intern v1.0.0 // indirect
- github.com/labstack/gommon v0.3.1 // indirect
+ github.com/labstack/gommon v0.4.2 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
- github.com/mattn/go-colorable v0.1.11 // indirect
- github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.1 // indirect
- golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
- golang.org/x/net v0.8.0 // indirect
- golang.org/x/sys v0.6.0 // indirect
- golang.org/x/text v0.8.0 // indirect
- golang.org/x/tools v0.7.0 // indirect
+ github.com/valyala/fasttemplate v1.2.2 // indirect
+ golang.org/x/crypto v0.24.0 // indirect
+ golang.org/x/net v0.26.0 // indirect
+ golang.org/x/sys v0.21.0 // indirect
+ golang.org/x/text v0.16.0 // indirect
+ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
- gopkg.in/yaml.v3 v3.0.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index 9886809..e7b1014 100644
--- a/go.sum
+++ b/go.sum
@@ -23,6 +23,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -30,19 +31,25 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
+github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -50,10 +57,15 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
@@ -61,30 +73,45 @@ github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
-golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
+golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
+golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -95,27 +122,47 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
+golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
+golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
+golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
+golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -128,5 +175,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
-gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=