Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenAPI vendor module update #399

Merged
merged 6 commits into from
Dec 1, 2021
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Unreleased changes are available as `avenga/couper:edge` container.
* exclude file descriptor limit startup-logs for Windows ([#396](https://github.com/avenga/couper/pull/396), [#383](https://github.com/avenga/couper/pull/383))
* possible race conditions while updating JWKS for the [JWT access control](./docs/REFERENCE.md#jwt-block) ([#398](https://github.com/avenga/couper/pull/398))

* **Dependencies**
* Update modules for [OpenAPI](./docs/REFERENCE.md#openapi-block) validation ([#399](https://github.com/avenga/couper/pull/399))
* `github.com/getkin/kin-openapi v0.49.0` => `github.com/getkin/kin-openapi v0.83.0`

---

## [1.6](https://github.com/avenga/couper/releases/tag/1.6)
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1
github.com/docker/go-units v0.4.0
github.com/fatih/color v1.10.0
github.com/getkin/kin-openapi v0.49.0
github.com/getkin/kin-openapi v0.83.0
github.com/hashicorp/hcl/v2 v2.10.1
github.com/jimlambrt/go-oauth-pkce-code-verifier v0.0.0-20201220003123-6363600dffda
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
Expand Down Expand Up @@ -57,8 +57,8 @@ require (
github.com/jonboulle/clockwork v0.2.0 // indirect
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
go.opentelemetry.io/otel/internal/metric v0.23.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/getkin/kin-openapi v0.49.0 h1:nKSq662fS0kZ11+Wu3FLg3GQGL0UuH1VxF8wV1QuDEU=
github.com/getkin/kin-openapi v0.49.0/go.mod h1:ZJSfy1PxJv2QQvH9EdBj3nupRTVvV42mkW6zKUlRBwk=
github.com/getkin/kin-openapi v0.83.0 h1:qQbfSsapSPuRS73xhElJ85bWFo2REHNXBXAQ1kqqlCE=
github.com/getkin/kin-openapi v0.83.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
Expand Down Expand Up @@ -164,6 +168,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
Expand Down Expand Up @@ -201,8 +206,12 @@ github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
Expand Down Expand Up @@ -443,6 +452,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
4 changes: 2 additions & 2 deletions handler/transport/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,15 @@ func TestBackend_RoundTrip_Validation(t *testing.T) {
http.MethodPost,
"/get",
"backend validation error",
"'POST /get': Path doesn't support the HTTP method",
"'POST /get': method not allowed",
},
{
"invalid request, IgnoreRequestViolations",
&config.OpenAPI{File: "testdata/upstream.yaml", IgnoreRequestViolations: true, IgnoreResponseViolations: true},
http.MethodPost,
"/get",
"",
"'POST /get': Path doesn't support the HTTP method",
"'POST /get': method not allowed",
},
{
"invalid response",
Expand Down
22 changes: 12 additions & 10 deletions handler/validation/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import (

"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/getkin/kin-openapi/routers"
"github.com/getkin/kin-openapi/routers/legacy"

"github.com/avenga/couper/config/request"
"github.com/avenga/couper/eval"
)

var routers sync.Map
var routersStore sync.Map

type OpenAPI struct {
options *OpenAPIOptions
Expand All @@ -31,10 +33,10 @@ func NewOpenAPI(opts *OpenAPIOptions) *OpenAPI {
}
}

func (v *OpenAPI) getRouter(key, origin string) (*openapi3filter.Router, error) {
router, exists := routers.Load(key)
func (v *OpenAPI) getRouter(key, origin string) (routers.Router, error) {
router, exists := routersStore.Load(key)
if !exists {
clonedSwagger := cloneSwagger(v.options.swagger)
clonedSwagger := cloneSwagger(v.options.doc)

var newServers []string
for _, s := range clonedSwagger.Servers {
Expand Down Expand Up @@ -69,16 +71,16 @@ func (v *OpenAPI) getRouter(key, origin string) (*openapi3filter.Router, error)
clonedSwagger.AddServer(&openapi3.Server{URL: ns})
}

r := openapi3filter.NewRouter()
if err := r.AddSwagger(clonedSwagger); err != nil {
r, err := legacy.NewRouter(clonedSwagger)
if err != nil {
return nil, err
}

routers.Store(key, r)
routersStore.Store(key, r)
return r, nil
}

return router.(*openapi3filter.Router), nil
return router.(routers.Router), nil
}

func (v *OpenAPI) ValidateRequest(req *http.Request, key string) (*openapi3filter.RequestValidationInput, error) {
Expand All @@ -101,7 +103,7 @@ func (v *OpenAPI) ValidateRequest(req *http.Request, key string) (*openapi3filte
return nil, nil
}

route, pathParams, err := router.FindRoute(req.Method, &serverURL)
route, pathParams, err := router.FindRoute(req)
if err != nil {
err = fmt.Errorf("'%s %s': %w", req.Method, req.URL.Path, err)
if ctx, ok := req.Context().Value(request.OpenAPI).(*OpenAPIContext); ok {
Expand Down Expand Up @@ -185,7 +187,7 @@ func (v *OpenAPI) ValidateResponse(beresp *http.Response, requestValidationInput
return nil
}

func cloneSwagger(s *openapi3.Swagger) *openapi3.Swagger {
func cloneSwagger(s *openapi3.T) *openapi3.T {
sw := *s
// this is not a deep clone; we only want to add servers
sw.Servers = s.Servers[:]
Expand Down
6 changes: 3 additions & 3 deletions handler/validation/openapi_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type OpenAPIOptions struct {
ignoreRequestViolations bool
ignoreResponseViolations bool
filterOptions *openapi3filter.Options
swagger *openapi3.Swagger
doc *openapi3.T
}

// NewOpenAPIOptions takes a list of openAPI configuration due to merging configurations.
Expand Down Expand Up @@ -45,7 +45,7 @@ func NewOpenAPIOptionsFromBytes(openapi *config.OpenAPI, bytes []byte) (*OpenAPI
return nil, nil
}

swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(bytes)
doc, err := openapi3.NewLoader().LoadFromData(bytes)
if err != nil {
return nil, fmt.Errorf("error loading openapi file: %w", err)
}
Expand All @@ -63,6 +63,6 @@ func NewOpenAPIOptionsFromBytes(openapi *config.OpenAPI, bytes []byte) (*OpenAPI
},
ignoreRequestViolations: openapi.IgnoreRequestViolations,
ignoreResponseViolations: openapi.IgnoreResponseViolations,
swagger: swagger,
doc: doc,
}, nil
}
4 changes: 2 additions & 2 deletions handler/validation/openapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ func TestOpenAPIValidator_ValidateRequest(t *testing.T) {
wantBody bool
wantErrLog string
}{
{"GET without required query", "/a?b", nil, false, "backend validation error: Parameter 'b' in query has an error: must have a value: must have a value"},
{"GET without required query", "/a?b", nil, false, `backend validation error: parameter "b" in query has an error: value is required but missing: value is required but missing`},
{"GET with required query", "/a?b=value", nil, false, ""},
{"GET with required path", "/a/value", nil, false, ""},
{"GET with required path missing", "/a//", nil, false, "backend validation error: Parameter 'b' in query has an error: must have a value: must have a value"},
{"GET with required path missing", "/a//", nil, false, `backend validation error: parameter "b" in query has an error: value is required but missing: value is required but missing`},
{"GET with optional query", "/b", nil, false, ""},
{"GET with optional path param", "/b/a", nil, false, ""},
{"GET with required json body", "/json", strings.NewReader(`["hans", "wurst"]`), true, ""},
Expand Down
4 changes: 0 additions & 4 deletions handler/validation/testdata/backend_04_openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ servers:
variables:
sub:
default: 'api'
- url: 'http://{broken/v1'
variables:
broken:
default: https://api.example.com
- url: 'https://{sub}.example.com/anything'
variables:
sub:
Expand Down
27 changes: 15 additions & 12 deletions server/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"strings"

"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/getkin/kin-openapi/pathpattern"
"github.com/getkin/kin-openapi/routers"
"github.com/getkin/kin-openapi/routers/legacy/pathpattern"

"github.com/avenga/couper/config"
"github.com/avenga/couper/config/request"
Expand All @@ -24,6 +24,7 @@ import (
type Mux struct {
endpointRoot *pathpattern.Node
fileRoot *pathpattern.Node
handler map[*routers.Route]http.Handler
opts *runtime.MuxOptions
spaRoot *pathpattern.Node
}
Expand Down Expand Up @@ -57,6 +58,7 @@ func NewMux(options *runtime.MuxOptions) *Mux {
endpointRoot: &pathpattern.Node{},
fileRoot: &pathpattern.Node{},
spaRoot: &pathpattern.Node{},
handler: make(map[*routers.Route]http.Handler),
}

for path, h := range opts.EndpointRoutes {
Expand Down Expand Up @@ -118,21 +120,22 @@ func (m *Mux) mustAddRoute(root *pathpattern.Node, methods []string, path string
serverOpts = optsHandler.Options()
}

node.Value = &openapi3filter.Route{
Method: method,
Path: path,
Handler: handler,
node.Value = &routers.Route{
Method: method,
Path: path,
Server: &openapi3.Server{Variables: map[string]*openapi3.ServerVariable{
serverOptionsKey: {Default: serverOpts},
serverOptionsKey: {Default: fmt.Sprintf("%#v", serverOpts)},
}},
}

m.handler[node.Value.(*routers.Route)] = handler
}

return m
}

func (m *Mux) FindHandler(req *http.Request) http.Handler {
var route *openapi3filter.Route
var route *routers.Route

node, paramValues := m.match(m.endpointRoot, req)
if node == nil {
Expand Down Expand Up @@ -160,7 +163,7 @@ func (m *Mux) FindHandler(req *http.Request) http.Handler {
}
}

route, _ = node.Value.(*openapi3filter.Route)
route, _ = node.Value.(*routers.Route)

pathParams := make(request.PathParameter, len(paramValues))
paramKeys := node.VariableNames
Expand All @@ -181,7 +184,7 @@ func (m *Mux) FindHandler(req *http.Request) http.Handler {
ctx = context.WithValue(ctx, request.PathParams, pathParams)
*req = *req.WithContext(ctx)

return route.Handler
return m.handler[route]
}

func (m *Mux) match(root *pathpattern.Node, req *http.Request) (*pathpattern.Node, []string) {
Expand All @@ -196,8 +199,8 @@ func (m *Mux) hasFileResponse(req *http.Request) (http.Handler, bool) {
return nil, false
}

route := node.Value.(*openapi3filter.Route)
fileHandler := route.Handler
route := node.Value.(*routers.Route)
fileHandler := m.handler[route]
unprotectedHandler := getChildHandler(fileHandler)
if fh, ok := unprotectedHandler.(*handler.File); ok {
return fileHandler, fh.HasResponse(req)
Expand Down
3 changes: 3 additions & 0 deletions vendor/github.com/getkin/kin-openapi/jsoninfo/field_info.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions vendor/github.com/getkin/kin-openapi/jsoninfo/marshal.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions vendor/github.com/getkin/kin-openapi/jsoninfo/unmarshal.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading