validator

package
v0.107.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 6, 2024 License: MIT, MIT Imports: 10 Imported by: 0

README



libopenapi

Enterprise grade OpenAPI validation tools for golang.

Pipeline codecov discord Docs

A validation module for libopenapi.

libopenapi-validator will validate the following elements against an OpenAPI 3+ specification

  • http.Request - Validates the request against the OpenAPI specification
  • http.Response - Validates the response against the OpenAPI specification
  • libopenapi.Document - Validates the OpenAPI document against the OpenAPI specification
  • base.Schema - Validates a schema against a JSON or YAML blob / unmarshalled object

👉👉 Check out the full documentation 👈👈


Installation

go get github.com/pb33f/libopenapi-validator

Documentation

libopenapi and libopenapi-validator are products of Princess Beef Heavy Industries, LLC

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Validator

type Validator interface {

	// ValidateHttpRequest will validate an *http.Request object against an OpenAPI 3+ document.
	// The path, query, cookie and header parameters and request body are validated.
	ValidateHttpRequest(request *http.Request) (bool, []*errors.ValidationError)
	// ValidateHttpRequestSync will validate an *http.Request object against an OpenAPI 3+ document syncronously and without spawning any goroutines.
	// The path, query, cookie and header parameters and request body are validated.
	ValidateHttpRequestSync(request *http.Request) (bool, []*errors.ValidationError)

	// ValidateHttpResponse will an *http.Response object against an OpenAPI 3+ document.
	// The response body is validated. The request is only used to extract the correct reponse from the spec.
	ValidateHttpResponse(request *http.Request, response *http.Response) (bool, []*errors.ValidationError)

	// ValidateHttpRequestResponse will validate both the *http.Request and *http.Response objects against an OpenAPI 3+ document.
	// The path, query, cookie and header parameters and request and response body are validated.
	ValidateHttpRequestResponse(request *http.Request, response *http.Response) (bool, []*errors.ValidationError)

	// ValidateDocument will validate an OpenAPI 3+ document against the 3.0 or 3.1 OpenAPI 3+ specification
	ValidateDocument() (bool, []*errors.ValidationError)

	// GetParameterValidator will return a parameters.ParameterValidator instance used to validate parameters
	GetParameterValidator() parameters.ParameterValidator

	// GetRequestBodyValidator will return a parameters.RequestBodyValidator instance used to validate request bodies
	GetRequestBodyValidator() requests.RequestBodyValidator

	// GetResponseBodyValidator will return a parameters.ResponseBodyValidator instance used to validate response bodies
	GetResponseBodyValidator() responses.ResponseBodyValidator
}

Validator provides a coarse grained interface for validating an OpenAPI 3+ documents. There are three primary use-cases for validation

Validating *http.Request objects against and OpenAPI 3+ document Validating *http.Response objects against an OpenAPI 3+ document Validating an OpenAPI 3+ document against the OpenAPI 3+ specification

func NewValidator

func NewValidator(document libopenapi.Document) (Validator, []error)

NewValidator will create a new Validator from an OpenAPI 3+ document

Example (ValidateDocument)
// 1. Load the OpenAPI 3+ spec into a byte array
petstore, err := os.ReadFile("test_specs/invalid_31.yaml")

if err != nil {
	panic(err)
}

// 2. Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocument(petstore)

if docErrs != nil {
	panic(docErrs)
}

// 3. Create a new validator
docValidator, validatorErrs := NewValidator(document)

if validatorErrs != nil {
	panic(validatorErrs)
}

// 4. Validate!
valid, validationErrs := docValidator.ValidateDocument()

if !valid {
	for i, e := range validationErrs {
		// 5. Handle the error
		fmt.Printf("%d: Type: %s, Failure: %s\n", i, e.ValidationType, e.Message)
		fmt.Printf("Fix: %s\n\n", e.HowToFix)
	}
}
Output:

0: Type: schema, Failure: Document does not pass validation
Fix: Ensure that the object being submitted, matches the schema correctly
Example (ValidateHttpRequest)
// 1. Load the OpenAPI 3+ spec into a byte array
petstore, err := os.ReadFile("test_specs/petstorev3.json")

if err != nil {
	panic(err)
}

// 2. Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocument(petstore)

if docErrs != nil {
	panic(docErrs)
}

// 3. Create a new validator
docValidator, validatorErrs := NewValidator(document)

if validatorErrs != nil {
	panic(validatorErrs)
}

// 4. Create a new *http.Request (normally, this would be where the host application will pass in the request)
request, _ := http.NewRequest(http.MethodGet, "/pet/NotAValidPetId", nil)

// 5. Validate!
valid, validationErrs := docValidator.ValidateHttpRequest(request)

if !valid {
	for _, e := range validationErrs {
		// 5. Handle the error
		fmt.Printf("Type: %s, Failure: %s\n", e.ValidationType, e.Message)
	}
}
Output:

Type: security, Failure: API Key api_key not found in header
Type: parameter, Failure: Path parameter 'petId' is not a valid number
Example (ValidateHttpRequestResponse)
// 1. Load the OpenAPI 3+ spec into a byte array
petstore, err := os.ReadFile("test_specs/petstorev3.json")

if err != nil {
	panic(err)
}

// 2. Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocument(petstore)

if docErrs != nil {
	panic(docErrs)
}

// 3. Create a new validator
docValidator, validatorErrs := NewValidator(document)

if validatorErrs != nil {
	panic(validatorErrs)
}

// 6. Create a new *http.Request (normally, this would be where the host application will pass in the request)
request, _ := http.NewRequest(http.MethodGet, "/pet/findByStatus?status=sold", nil)

// 7. Simulate a request/response, in this case the contract returns a 200 with an array of pets.
// Normally, this would be where the host application would pass in the response.
recorder := httptest.NewRecorder()
handler := func(w http.ResponseWriter, r *http.Request) {

	// set return content type.
	w.Header().Set(helpers.ContentTypeHeader, helpers.JSONContentType)
	w.WriteHeader(http.StatusOK)

	// create a Pet
	body := map[string]interface{}{
		"id":   123,
		"name": "cotton",
		"category": map[string]interface{}{
			"id":   "NotAValidPetId", // this will fail, it should be an integer.
			"name": "dogs",
		},
		"photoUrls": []string{"https://pb33f.io"},
	}

	// marshal the request body into bytes.
	responseBodyBytes, _ := json.Marshal([]interface{}{body}) // operation returns an array of pets
	// return the response.
	_, _ = w.Write(responseBodyBytes)
}

// simulate request/response
handler(recorder, request)

// 7. Validate!
valid, validationErrs := docValidator.ValidateHttpRequestResponse(request, recorder.Result())

if !valid {
	for _, e := range validationErrs {
		// 5. Handle the error
		fmt.Printf("Type: %s, Failure: %s\n", e.ValidationType, e.Message)
		fmt.Printf("Schema Error: %s, Line: %d, Col: %d\n",
			e.SchemaValidationErrors[0].Reason,
			e.SchemaValidationErrors[0].Line,
			e.SchemaValidationErrors[0].Column)
	}
}
Output:

Type: response, Failure: 200 response body for '/pet/findByStatus' failed to validate schema
Schema Error: expected integer, but got string, Line: 19, Col: 27
Example (ValidateHttpRequestSync)
// 1. Load the OpenAPI 3+ spec into a byte array
petstore, err := os.ReadFile("test_specs/petstorev3.json")

if err != nil {
	panic(err)
}

// 2. Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocument(petstore)

if docErrs != nil {
	panic(docErrs)
}

// 3. Create a new validator
docValidator, validatorErrs := NewValidator(document)

if validatorErrs != nil {
	panic(validatorErrs)
}

// 4. Create a new *http.Request (normally, this would be where the host application will pass in the request)
request, _ := http.NewRequest(http.MethodGet, "/pet/NotAValidPetId", nil)

// 5. Validate!
valid, validationErrs := docValidator.ValidateHttpRequestSync(request)

if !valid {
	for _, e := range validationErrs {
		// 5. Handle the error
		fmt.Printf("Type: %s, Failure: %s\n", e.ValidationType, e.Message)
	}
}
// Type: parameter, Failure: Path parameter 'petId' is not a valid number
Output:

Example (ValidateHttpResponse)
// 1. Load the OpenAPI 3+ spec into a byte array
petstore, err := os.ReadFile("test_specs/petstorev3.json")

if err != nil {
	panic(err)
}

// 2. Create a new OpenAPI document using libopenapi
document, docErrs := libopenapi.NewDocument(petstore)

if docErrs != nil {
	panic(docErrs)
}

// 3. Create a new validator
docValidator, validatorErrs := NewValidator(document)

if validatorErrs != nil {
	panic(validatorErrs)
}

// 6. Create a new *http.Request (normally, this would be where the host application will pass in the request)
request, _ := http.NewRequest(http.MethodGet, "/pet/findByStatus?status=sold", nil)

// 7. Simulate a request/response, in this case the contract returns a 200 with an array of pets.
// Normally, this would be where the host application would pass in the response.
recorder := httptest.NewRecorder()
handler := func(w http.ResponseWriter, r *http.Request) {

	// set return content type.
	w.Header().Set(helpers.ContentTypeHeader, helpers.JSONContentType)
	w.WriteHeader(http.StatusOK)

	// create a Pet
	body := map[string]interface{}{
		"id":   123,
		"name": "cotton",
		"category": map[string]interface{}{
			"id":   "NotAValidPetId", // this will fail, it should be an integer.
			"name": "dogs",
		},
		"photoUrls": []string{"https://pb33f.io"},
	}

	// marshal the request body into bytes.
	responseBodyBytes, _ := json.Marshal([]interface{}{body}) // operation returns an array of pets
	// return the response.
	_, _ = w.Write(responseBodyBytes)
}

// simulate request/response
handler(recorder, request)

// 7. Validate the response only
valid, validationErrs := docValidator.ValidateHttpResponse(request, recorder.Result())

if !valid {
	for _, e := range validationErrs {
		// 5. Handle the error
		fmt.Printf("Type: %s, Failure: %s\n", e.ValidationType, e.Message)
		fmt.Printf("Schema Error: %s, Line: %d, Col: %d\n",
			e.SchemaValidationErrors[0].Reason,
			e.SchemaValidationErrors[0].Line,
			e.SchemaValidationErrors[0].Column)
	}
}
Output:

Type: response, Failure: 200 response body for '/pet/findByStatus' failed to validate schema
Schema Error: expected integer, but got string, Line: 19, Col: 27

func NewValidatorFromV3Model

func NewValidatorFromV3Model(m *v3.Document) Validator

NewValidatorFromV3Model will create a new Validator from an OpenAPI Model

Directories

Path Synopsis
Package errors contains all the error types used by the validator
Package errors contains all the error types used by the validator
Package helpers contains helper and utility functions used by the validator.
Package helpers contains helper and utility functions used by the validator.
Package parameters contains all the logic, models and interfaces for validating OpenAPI 3+ Parameters.
Package parameters contains all the logic, models and interfaces for validating OpenAPI 3+ Parameters.
Package paths contains all the logic, models and interfaces for validating OpenAPI 3+ Paths.
Package paths contains all the logic, models and interfaces for validating OpenAPI 3+ Paths.
Package requests contains all the logic, models and interfaces for validating OpenAPI 3+ Requests.
Package requests contains all the logic, models and interfaces for validating OpenAPI 3+ Requests.
Package responses contains all the logic, models and interfaces for validating OpenAPI 3+ Responses The package depends on *http.Response
Package responses contains all the logic, models and interfaces for validating OpenAPI 3+ Responses The package depends on *http.Response
Package schema_validation contains all the logic, models and interfaces for validating OpenAPI 3+ Schemas.
Package schema_validation contains all the logic, models and interfaces for validating OpenAPI 3+ Schemas.
openapi_schemas
Package openapi_schemas contains the OpenAPI 3.0 and 3.1 schemas that are loaded from libopenapi, or our own fork of the official OpenAPI repo specifications.
Package openapi_schemas contains the OpenAPI 3.0 and 3.1 schemas that are loaded from libopenapi, or our own fork of the official OpenAPI repo specifications.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL