diff --git a/go.mod b/go.mod index d46cfba..5820352 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,13 @@ module github.com/davidebianchi/gswagger go 1.20 require ( - github.com/getkin/kin-openapi v0.125.0 + github.com/getkin/kin-openapi v0.126.0 github.com/ghodss/yaml v1.0.0 - github.com/go-openapi/swag v0.22.8 // indirect - github.com/gorilla/mux v1.8.1 - github.com/labstack/echo/v4 v4.12.0 - github.com/mailru/easyjson v0.7.7 // indirect - github.com/stretchr/testify v1.9.0 -) - -require ( github.com/gofiber/fiber/v2 v2.52.5 + github.com/gorilla/mux v1.8.1 github.com/invopop/jsonschema v0.12.0 + github.com/labstack/echo/v4 v4.12.0 + github.com/stretchr/testify v1.9.0 ) require ( @@ -22,12 +17,14 @@ require ( github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/google/uuid v1.5.0 // indirect - github.com/invopop/yaml v0.2.0 // indirect + github.com/invopop/yaml v0.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.17.0 // indirect github.com/labstack/gommon v0.4.2 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect diff --git a/go.sum b/go.sum index c17df44..afd59c7 100644 --- a/go.sum +++ b/go.sum @@ -6,14 +6,14 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/getkin/kin-openapi v0.125.0 h1:jyQCyf2qXS1qvs2U00xQzkGCqYPhEhZDmSmVt65fXno= -github.com/getkin/kin-openapi v0.125.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM= +github.com/getkin/kin-openapi v0.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY= +github.com/getkin/kin-openapi v0.126.0/go.mod h1:7mONz8IwmSRg6RttPu6v8U/OJ+gr+J99qSFNjPGSQqw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw= -github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= @@ -23,8 +23,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= -github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= +github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= 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/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= @@ -80,6 +80,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -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= diff --git a/route.go b/route.go index 7eb16a6..33f903f 100644 --- a/route.go +++ b/route.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "path" + "regexp" "sort" "strings" @@ -289,15 +290,18 @@ func (r Router[_, _]) addContentToOASSchema(content Content) (openapi3.Content, func getPathParamsAutoComplete(schema Definitions, path string) ParameterValue { if schema.PathParams == nil { - pathParams := strings.Split(path, "/") - for _, param := range pathParams { - if strings.HasPrefix(param, "{") && strings.HasSuffix(param, "}") { - if schema.PathParams == nil { - schema.PathParams = make(ParameterValue) - } - param = strings.Replace(param, "{", "", 1) - param = strings.Replace(param, "}", "", 1) - schema.PathParams[param] = Parameter{ + re := regexp.MustCompile(`\{([^}]+)\}`) + segments := strings.Split(path, "/") + for _, segment := range segments { + params := re.FindAllStringSubmatch(segment, -1) + if len(params) == 0 { + continue + } + if schema.PathParams == nil { + schema.PathParams = make(ParameterValue) + } + for _, param := range params { + schema.PathParams[param[1]] = Parameter{ Schema: &Schema{Value: ""}, } } diff --git a/route_test.go b/route_test.go index 40e306d..80d24c3 100644 --- a/route_test.go +++ b/route_test.go @@ -187,7 +187,7 @@ func TestAddRoutes(t *testing.T) { fixturesPath: "testdata/params.json", }, { - name: "schema without params autofilled", + name: "schema without explicit params autofill them", routes: func(t *testing.T, router *TestRouter) { _, err := router.AddRoute(http.MethodGet, "/users/{userId}", okHandler, Definitions{ Querystring: ParameterValue{ @@ -200,8 +200,11 @@ func TestAddRoutes(t *testing.T) { _, err = router.AddRoute(http.MethodGet, "/cars/{carId}/drivers/{driverId}", okHandler, Definitions{}) require.NoError(t, err) + + _, err = router.AddRoute(http.MethodGet, "/files/{name}.{extension}", okHandler, Definitions{}) + require.NoError(t, err) }, - testPath: "/users/12", + testPath: "/files/myid.yaml", fixturesPath: "testdata/params-autofill.json", }, { @@ -1118,3 +1121,61 @@ func getBaseSwagger(t *testing.T) *openapi3.T { }, } } + +func TestGetPathParamsAutoComplete(t *testing.T) { + testCases := map[string]struct { + schemaDefinition Definitions + path string + expected ParameterValue + }{ + "no path params": { + schemaDefinition: Definitions{}, + path: "/users", + expected: nil, + }, + "with path params": { + schemaDefinition: Definitions{}, + path: "/users/{userId}", + expected: ParameterValue{ + "userId": { + Schema: &Schema{Value: ""}, + }, + }, + }, + "with multiple path params": { + schemaDefinition: Definitions{}, + path: "/foo/{bar}.{taz}", + expected: ParameterValue{ + "bar": { + Schema: &Schema{Value: ""}, + }, + "taz": { + Schema: &Schema{Value: ""}, + }, + }, + }, + "with nested multiple path params": { + schemaDefinition: Definitions{}, + path: "/foo/{bar}.{taz}/{baz}/ok", + expected: ParameterValue{ + "bar": { + Schema: &Schema{Value: ""}, + }, + "taz": { + Schema: &Schema{Value: ""}, + }, + "baz": { + Schema: &Schema{Value: ""}, + }, + }, + }, + } + + for name, test := range testCases { + t.Run(name, func(t *testing.T) { + actual := getPathParamsAutoComplete(test.schemaDefinition, test.path) + + require.Equal(t, test.expected, actual) + }) + } +} diff --git a/testdata/params-autofill.json b/testdata/params-autofill.json index a4fea47..b4d040a 100644 --- a/testdata/params-autofill.json +++ b/testdata/params-autofill.json @@ -57,6 +57,33 @@ } } } + }, + "/files/{name}.{extension}": { + "get": { + "parameters": [ + { + "in": "path", + "name": "extension", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "name", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "default": { + "description": "" + } + } + } } } }