Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rolling-shutter/keyper/kprapi/kprapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ func (srv *Server) waitShutdown(ctx context.Context) error {
func (srv *Server) setupAPIRouter(swagger *openapi3.T) http.Handler {
router := chi.NewRouter()

router.Use(chimiddleware.OapiRequestValidator(swagger))
router.Use(kproapi.ConfigMiddleware(srv.config.GetEnableWriteOperations()))

router.Use(chimiddleware.OapiRequestValidator(swagger))
_ = kproapi.HandlerFromMux(srv, router)

return router
Expand Down
19 changes: 18 additions & 1 deletion rolling-shutter/keyper/kproapi/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package kproapi
import (
"encoding/json"
"net/http"
"regexp"
"strings"

"github.com/getkin/kin-openapi/openapi3"
)
Expand Down Expand Up @@ -34,8 +36,23 @@ func shouldEnableEndpoint(operation *openapi3.Operation, enableWriteOperations b

// findOperation looks up the OpenAPI operation for the given path and method.
func findOperation(spec *openapi3.T, path string, method string) *openapi3.Operation {
pathItem := spec.Paths.Find(path)
pathItem := spec.Paths.Find(path) // first try to find the path in the spec
if pathItem == nil {
for specPath, pItem := range spec.Paths { // fallback for path containing parameters
rePath := "^" + regexp.QuoteMeta(specPath)
rePath = strings.ReplaceAll(rePath, `\{`, "{")
rePath = strings.ReplaceAll(rePath, `\}`, "}")
rePath = regexp.MustCompile(`\{[^/]+\}`).ReplaceAllString(rePath, `[^/]+`)
rePath += "$"

if matched, _ := regexp.MatchString(rePath, path); matched {
pathItem = pItem
break
}
}
}

if pathItem == nil { // if no path is found still, return nil
return nil
}

Expand Down
52 changes: 52 additions & 0 deletions rolling-shutter/keyper/kproapi/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,58 @@ func TestFindOperation(t *testing.T) {
}
}

func TestFindOperation_ParameterizedPaths(t *testing.T) {
spec := &openapi3.T{
Paths: openapi3.Paths{
"/test/{id}": &openapi3.PathItem{
Get: &openapi3.Operation{},
},
"/tests/{id}/items/{name}": &openapi3.PathItem{
Post: &openapi3.Operation{},
},
},
}

tests := []struct {
name string
path string
method string
want *openapi3.Operation
}{
{
name: "match single parameterized path",
path: "/test/123",
method: http.MethodGet,
want: spec.Paths.Find("/test/{id}").Get,
},
{
name: "match nested parameterized path",
path: "/tests/123/items/xyz456",
method: http.MethodPost,
want: spec.Paths.Find("/tests/{id}/items/{name}").Post,
},
{
name: "no match for wrong structure",
path: "/tests/123/items", // missing /{name}
method: http.MethodPost,
want: nil,
},
{
name: "non-existent parameterized path",
path: "/unknown/123",
method: http.MethodGet,
want: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := findOperation(spec, tt.path, tt.method)
assert.Equal(t, tt.want, got)
})
}
}

func TestConfigMiddleware(t *testing.T) {
// Create a test spec with both read-only and write operations
spec := &openapi3.T{
Expand Down