mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-20 01:19:35 +00:00
108 lines
2.6 KiB
Go
108 lines
2.6 KiB
Go
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
|
|
"github.com/getkin/kin-openapi/openapi3"
|
|
"github.com/getkin/kin-openapi/openapi3filter"
|
|
"github.com/getkin/kin-openapi/routers"
|
|
legacyrouter "github.com/getkin/kin-openapi/routers/legacy"
|
|
|
|
"github.com/up9inc/mizu/shared"
|
|
"github.com/up9inc/mizu/tap/api"
|
|
)
|
|
|
|
const (
|
|
ContractNotApplicable api.ContractStatus = 0
|
|
ContractPassed api.ContractStatus = 1
|
|
ContractFailed api.ContractStatus = 2
|
|
)
|
|
|
|
func loadOAS(ctx context.Context) (doc *openapi3.T, contractContent string, router routers.Router, err error) {
|
|
path := fmt.Sprintf("%s%s", shared.ConfigDirPath, shared.ContractFileName)
|
|
bytes, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return
|
|
}
|
|
contractContent = string(bytes)
|
|
loader := &openapi3.Loader{Context: ctx}
|
|
doc, _ = loader.LoadFromData(bytes)
|
|
err = doc.Validate(ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
router, _ = legacyrouter.NewRouter(doc)
|
|
return
|
|
}
|
|
|
|
func validateOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response) (isValid bool, reqErr error, resErr error) {
|
|
isValid = true
|
|
reqErr = nil
|
|
resErr = nil
|
|
|
|
// Find route
|
|
route, pathParams, err := router.FindRoute(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// Validate request
|
|
requestValidationInput := &openapi3filter.RequestValidationInput{
|
|
Request: req,
|
|
PathParams: pathParams,
|
|
Route: route,
|
|
}
|
|
if reqErr = openapi3filter.ValidateRequest(ctx, requestValidationInput); reqErr != nil {
|
|
isValid = false
|
|
}
|
|
|
|
responseValidationInput := &openapi3filter.ResponseValidationInput{
|
|
RequestValidationInput: requestValidationInput,
|
|
Status: res.StatusCode,
|
|
Header: res.Header,
|
|
}
|
|
|
|
if res.Body != nil {
|
|
body, _ := ioutil.ReadAll(res.Body)
|
|
res.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
responseValidationInput.SetBodyBytes(body)
|
|
}
|
|
|
|
// Validate response.
|
|
if resErr = openapi3filter.ValidateResponse(ctx, responseValidationInput); resErr != nil {
|
|
isValid = false
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func handleOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response, contractContent string) (contract api.Contract) {
|
|
contract = api.Contract{
|
|
Content: contractContent,
|
|
Status: ContractNotApplicable,
|
|
}
|
|
|
|
isValid, reqErr, resErr := validateOAS(ctx, doc, router, req, res)
|
|
if isValid {
|
|
contract.Status = ContractPassed
|
|
} else {
|
|
contract.Status = ContractFailed
|
|
if reqErr != nil {
|
|
contract.RequestReason = reqErr.Error()
|
|
} else {
|
|
contract.RequestReason = ""
|
|
}
|
|
if resErr != nil {
|
|
contract.ResponseReason = resErr.Error()
|
|
} else {
|
|
contract.ResponseReason = ""
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|