Skip to content

Commit 3563d41

Browse files
feat: add support to multiple params (#162)
1 parent 1802f29 commit 3563d41

File tree

5 files changed

+118
-30
lines changed

5 files changed

+118
-30
lines changed

go.mod

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,28 @@ module github.com/davidebianchi/gswagger
33
go 1.20
44

55
require (
6-
github.com/getkin/kin-openapi v0.125.0
6+
github.com/getkin/kin-openapi v0.126.0
77
github.com/ghodss/yaml v1.0.0
8-
github.com/go-openapi/swag v0.22.8 // indirect
8+
github.com/gofiber/fiber/v2 v2.52.5
99
github.com/gorilla/mux v1.8.1
10+
github.com/invopop/jsonschema v0.12.0
1011
github.com/labstack/echo/v4 v4.12.0
11-
github.com/mailru/easyjson v0.7.7 // indirect
1212
github.com/stretchr/testify v1.9.0
1313
)
1414

15-
require (
16-
github.com/gofiber/fiber/v2 v2.52.5
17-
github.com/invopop/jsonschema v0.12.0
18-
)
19-
2015
require (
2116
github.com/andybalholm/brotli v1.0.5 // indirect
2217
github.com/bahlo/generic-list-go v0.2.0 // indirect
2318
github.com/buger/jsonparser v1.1.1 // indirect
2419
github.com/davecgh/go-spew v1.1.1 // indirect
25-
github.com/go-openapi/jsonpointer v0.20.2 // indirect
20+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
21+
github.com/go-openapi/swag v0.23.0 // indirect
2622
github.com/google/uuid v1.5.0 // indirect
27-
github.com/invopop/yaml v0.2.0 // indirect
23+
github.com/invopop/yaml v0.3.1 // indirect
2824
github.com/josharian/intern v1.0.0 // indirect
2925
github.com/klauspost/compress v1.17.0 // indirect
3026
github.com/labstack/gommon v0.4.2 // indirect
27+
github.com/mailru/easyjson v0.7.7 // indirect
3128
github.com/mattn/go-colorable v0.1.13 // indirect
3229
github.com/mattn/go-isatty v0.0.20 // indirect
3330
github.com/mattn/go-runewidth v0.0.15 // indirect

go.sum

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMU
66
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
77
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
88
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9-
github.com/getkin/kin-openapi v0.125.0 h1:jyQCyf2qXS1qvs2U00xQzkGCqYPhEhZDmSmVt65fXno=
10-
github.com/getkin/kin-openapi v0.125.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
9+
github.com/getkin/kin-openapi v0.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY=
10+
github.com/getkin/kin-openapi v0.126.0/go.mod h1:7mONz8IwmSRg6RttPu6v8U/OJ+gr+J99qSFNjPGSQqw=
1111
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
1212
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
13-
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
14-
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
15-
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
16-
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
13+
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
14+
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
15+
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
16+
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
1717
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
1818
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
1919
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=
2323
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
2424
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
2525
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
26-
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
27-
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
26+
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
27+
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
2828
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
2929
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
3030
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
8080
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
8181
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
8282
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
83-
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8483
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
8584
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

route.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"path"
7+
"regexp"
78
"sort"
89
"strings"
910

@@ -289,15 +290,18 @@ func (r Router[_, _]) addContentToOASSchema(content Content) (openapi3.Content,
289290

290291
func getPathParamsAutoComplete(schema Definitions, path string) ParameterValue {
291292
if schema.PathParams == nil {
292-
pathParams := strings.Split(path, "/")
293-
for _, param := range pathParams {
294-
if strings.HasPrefix(param, "{") && strings.HasSuffix(param, "}") {
295-
if schema.PathParams == nil {
296-
schema.PathParams = make(ParameterValue)
297-
}
298-
param = strings.Replace(param, "{", "", 1)
299-
param = strings.Replace(param, "}", "", 1)
300-
schema.PathParams[param] = Parameter{
293+
re := regexp.MustCompile(`\{([^}]+)\}`)
294+
segments := strings.Split(path, "/")
295+
for _, segment := range segments {
296+
params := re.FindAllStringSubmatch(segment, -1)
297+
if len(params) == 0 {
298+
continue
299+
}
300+
if schema.PathParams == nil {
301+
schema.PathParams = make(ParameterValue)
302+
}
303+
for _, param := range params {
304+
schema.PathParams[param[1]] = Parameter{
301305
Schema: &Schema{Value: ""},
302306
}
303307
}

route_test.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func TestAddRoutes(t *testing.T) {
187187
fixturesPath: "testdata/params.json",
188188
},
189189
{
190-
name: "schema without params autofilled",
190+
name: "schema without explicit params autofill them",
191191
routes: func(t *testing.T, router *TestRouter) {
192192
_, err := router.AddRoute(http.MethodGet, "/users/{userId}", okHandler, Definitions{
193193
Querystring: ParameterValue{
@@ -200,8 +200,11 @@ func TestAddRoutes(t *testing.T) {
200200

201201
_, err = router.AddRoute(http.MethodGet, "/cars/{carId}/drivers/{driverId}", okHandler, Definitions{})
202202
require.NoError(t, err)
203+
204+
_, err = router.AddRoute(http.MethodGet, "/files/{name}.{extension}", okHandler, Definitions{})
205+
require.NoError(t, err)
203206
},
204-
testPath: "/users/12",
207+
testPath: "/files/myid.yaml",
205208
fixturesPath: "testdata/params-autofill.json",
206209
},
207210
{
@@ -1118,3 +1121,61 @@ func getBaseSwagger(t *testing.T) *openapi3.T {
11181121
},
11191122
}
11201123
}
1124+
1125+
func TestGetPathParamsAutoComplete(t *testing.T) {
1126+
testCases := map[string]struct {
1127+
schemaDefinition Definitions
1128+
path string
1129+
expected ParameterValue
1130+
}{
1131+
"no path params": {
1132+
schemaDefinition: Definitions{},
1133+
path: "/users",
1134+
expected: nil,
1135+
},
1136+
"with path params": {
1137+
schemaDefinition: Definitions{},
1138+
path: "/users/{userId}",
1139+
expected: ParameterValue{
1140+
"userId": {
1141+
Schema: &Schema{Value: ""},
1142+
},
1143+
},
1144+
},
1145+
"with multiple path params": {
1146+
schemaDefinition: Definitions{},
1147+
path: "/foo/{bar}.{taz}",
1148+
expected: ParameterValue{
1149+
"bar": {
1150+
Schema: &Schema{Value: ""},
1151+
},
1152+
"taz": {
1153+
Schema: &Schema{Value: ""},
1154+
},
1155+
},
1156+
},
1157+
"with nested multiple path params": {
1158+
schemaDefinition: Definitions{},
1159+
path: "/foo/{bar}.{taz}/{baz}/ok",
1160+
expected: ParameterValue{
1161+
"bar": {
1162+
Schema: &Schema{Value: ""},
1163+
},
1164+
"taz": {
1165+
Schema: &Schema{Value: ""},
1166+
},
1167+
"baz": {
1168+
Schema: &Schema{Value: ""},
1169+
},
1170+
},
1171+
},
1172+
}
1173+
1174+
for name, test := range testCases {
1175+
t.Run(name, func(t *testing.T) {
1176+
actual := getPathParamsAutoComplete(test.schemaDefinition, test.path)
1177+
1178+
require.Equal(t, test.expected, actual)
1179+
})
1180+
}
1181+
}

testdata/params-autofill.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,33 @@
5757
}
5858
}
5959
}
60+
},
61+
"/files/{name}.{extension}": {
62+
"get": {
63+
"parameters": [
64+
{
65+
"in": "path",
66+
"name": "extension",
67+
"required": true,
68+
"schema": {
69+
"type": "string"
70+
}
71+
},
72+
{
73+
"in": "path",
74+
"name": "name",
75+
"required": true,
76+
"schema": {
77+
"type": "string"
78+
}
79+
}
80+
],
81+
"responses": {
82+
"default": {
83+
"description": ""
84+
}
85+
}
86+
}
6087
}
6188
}
6289
}

0 commit comments

Comments
 (0)