Repository: swaggest/openapi-go (go)

Issue:
pathItem has a wrong key when using regexes.
Hi,
Following this [issue](https://github.com/swaggest/openapi-go/issues/45), there is a problem when using regexes on path.

Let's say I have 2 routes : `GET /users/{userID:[^/]+}` and `POST /users/{userID:[^/]+}`.

In `helper.go`, in `Spec.SetupOperation()`, we get the pathItem (l.40) from `s.Paths.MapOfPathItemValues` by using the path as key (so in this case, `/users/{userID:[^/]+}`). But at the end of the method, we set the new pathItem under the key `/users/{userID}` (the path without the regex). When we setup the operation for the next method, we get the pathItem under the key `/users/{userID:[^/]+}`, which is empty, so the first routes is overridden completely by the second one.

I think getting the `pathItem` after the regex substitution should solve the issue (so after l. 51, maybe at l.54 because the first use of `pathItem` is at line 55).

Pull request:
Fix path item resolution for unclean path
Resolves #49.

Patch:
diff --git a/go.mod b/go.mod
index 6e54fc2..a74fd8a 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.17
 
 require (
 	github.com/bool64/dev v0.2.22
-	github.com/stretchr/testify v1.8.0
+	github.com/stretchr/testify v1.8.1
 	github.com/swaggest/assertjson v1.7.0
 	github.com/swaggest/jsonschema-go v0.3.40
 	github.com/swaggest/refl v1.1.0
diff --git a/go.sum b/go.sum
index af6756b..072c670 100644
--- a/go.sum
+++ b/go.sum
@@ -56,10 +56,12 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/swaggest/assertjson v1.7.0 h1:SKw5Rn0LQs6UvmGrIdaKQbMR1R3ncXm5KNon+QJ7jtw=
 github.com/swaggest/assertjson v1.7.0/go.mod h1:vxMJMehbSVJd+dDWFCKv3QRZKNTpy/ktZKTz9LOEDng=
 github.com/swaggest/jsonschema-go v0.3.40 h1:9EqQ9RvtdW69xfYODmyEKWOSZ12x5eiK+wGD2EVh/L4=
diff --git a/openapi3/helper.go b/openapi3/helper.go
index 377f8e5..7d7f9b7 100644
--- a/openapi3/helper.go
+++ b/openapi3/helper.go
@@ -37,7 +37,6 @@ func (s *Spec) SetupOperation(method, path string, setup ...func(*Operation) err
 		return fmt.Errorf("unexpected http method: %s", method)
 	}
 
-	pathItem := s.Paths.MapOfPathItemValues[path]
 	pathParams := map[string]bool{}
 
 	if len(pathParametersSubmatches) > 0 {
@@ -52,6 +51,7 @@ func (s *Spec) SetupOperation(method, path string, setup ...func(*Operation) err
 
 	var errs []string
 
+	pathItem := s.Paths.MapOfPathItemValues[path]
 	operation := pathItem.MapOfOperationValues[method]
 
 	for _, f := range setup {


Test patch:
diff --git a/openapi3/helper_test.go b/openapi3/helper_test.go
index 19311a3..04630f3 100644
--- a/openapi3/helper_test.go
+++ b/openapi3/helper_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/swaggest/assertjson"
 	"github.com/swaggest/openapi-go/openapi3"
 )
 
@@ -77,3 +78,25 @@ func TestSpec_SetupOperation_pathRegex(t *testing.T) {
 		})
 	}
 }
+
+func TestSpec_SetupOperation_uncleanPath(t *testing.T) {
+	s := openapi3.Spec{}
+	f := func(operation *openapi3.Operation) error {
+		operation.WithParameters(openapi3.Parameter{In: openapi3.ParameterInPath, Name: "userID"}.ToParameterOrRef())
+
+		return nil
+	}
+
+	assert.NoError(t, s.SetupOperation(http.MethodGet, "/users/{userID:[^/]+}", f))
+	assert.NoError(t, s.SetupOperation(http.MethodPost, "/users/{userID:[^/]+}", f))
+
+	assertjson.EqualMarshal(t, []byte(`{
+	  "openapi":"","info":{"title":"","version":""},
+	  "paths":{
+		"/users/{userID}":{
+		  "get":{"parameters":[{"name":"userID","in":"path"}],"responses":{}},
+		  "post":{"parameters":[{"name":"userID","in":"path"}],"responses":{}}
+		}
+	  }
+	}`), s)
+}