Skip to content

Commit

Permalink
for what it's worth...
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Fenoll <[email protected]>
  • Loading branch information
fenollp committed Aug 26, 2021
1 parent 26962ef commit e707429
Show file tree
Hide file tree
Showing 14 changed files with 640 additions and 177 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ jobs:
if: matrix.go != '1.14'
- run: go test -tags xeipuuv ./...
- run: go test -tags xeipuuv -v -run TestRaceyPatternSchema -race ./...
env:
CGO_ENABLED: '1'
- run: |
cp openapi3/testdata/load_with_go_embed_test.go openapi3/
cat go.mod | sed 's%go 1.14%go 1.16%' >gomod && mv gomod go.mod
go test -tags xeipuuv ./...
if: matrix.go != '1.14'
- if: runner.os == 'Linux'
name: Errors must not be capitalized https://github.com/golang/go/wiki/CodeReviewComments#error-strings
run: |
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ require (
github.com/go-openapi/jsonpointer v0.19.5
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.5.1
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
2 changes: 1 addition & 1 deletion openapi3/race_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestRaceyPatternSchema(t *testing.T) {
require.NoError(t, err)

visit := func() {
err := schema.VisitJSONString("test")
err := schema.VisitData(nil, "test")
require.NoError(t, err)
}

Expand Down
149 changes: 12 additions & 137 deletions openapi3/schema.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package openapi3

import (
"context"
"errors"
"fmt"
"regexp"
"strconv"
Expand All @@ -9,6 +11,8 @@ import (
"github.com/go-openapi/jsonpointer"
)

var errSchema = errors.New("input does not match the schema")

// Float64Ptr is a helper for defining OpenAPI schemas.
func Float64Ptr(value float64) *float64 {
return &value
Expand Down Expand Up @@ -131,6 +135,11 @@ func (schema *Schema) VisitData(doc *T, data interface{}, opts ...SchemaValidati
return schema.visitData(doc, data, opts...)
}

// VisitJSON validates given data against schema only.
func (schema *Schema) VisitJSON(data interface{}, opts ...SchemaValidationOption) error {
return schema.VisitData(nil, data, opts...)
}

func NewSchema() *Schema {
return &Schema{}
}
Expand Down Expand Up @@ -559,140 +568,6 @@ func (schema *Schema) IsEmpty() bool {
return true
}

// func (schema *Schema) expectedType(settings *schemaValidationSettings, typ string) error {
// if settings.failfast {
// return errSchema
// }
// return &SchemaError{
// Value: typ,
// Schema: schema,
// SchemaField: "type",
// Reason: "Field must be set to " + schema.Type + " or not be present",
// }
// }

// func (schema *Schema) compilePattern() (err error) {
// if schema.compiledPattern, err = regexp.Compile(schema.Pattern); err != nil {
// return &SchemaError{
// Schema: schema,
// SchemaField: "pattern",
// Reason: fmt.Sprintf("cannot compile pattern %q: %v", schema.Pattern, err),
// }
// }
// return nil
// }

// type SchemaError struct {
// Value interface{}
// reversePath []string
// Schema *Schema
// SchemaField string
// Reason string
// Origin error
// }

// func markSchemaErrorKey(err error, key string) error {
// if v, ok := err.(*SchemaError); ok {
// v.reversePath = append(v.reversePath, key)
// return v
// }
// if v, ok := err.(MultiError); ok {
// for _, e := range v {
// _ = markSchemaErrorKey(e, key)
// }
// return v
// }
// return err
// }

// func markSchemaErrorIndex(err error, index int) error {
// if v, ok := err.(*SchemaError); ok {
// v.reversePath = append(v.reversePath, strconv.FormatInt(int64(index), 10))
// return v
// }
// if v, ok := err.(MultiError); ok {
// for _, e := range v {
// _ = markSchemaErrorIndex(e, index)
// }
// return v
// }
// return err
// }

// func (err *SchemaError) JSONPointer() []string {
// reversePath := err.reversePath
// path := append([]string(nil), reversePath...)
// for left, right := 0, len(path)-1; left < right; left, right = left+1, right-1 {
// path[left], path[right] = path[right], path[left]
// }
// return path
// }

// func (err *SchemaError) Error() string {
// if err.Origin != nil {
// return err.Origin.Error()
// }

// buf := bytes.NewBuffer(make([]byte, 0, 256))
// if len(err.reversePath) > 0 {
// buf.WriteString(`Error at "`)
// reversePath := err.reversePath
// for i := len(reversePath) - 1; i >= 0; i-- {
// buf.WriteByte('/')
// buf.WriteString(reversePath[i])
// }
// buf.WriteString(`": `)
// }
// reason := err.Reason
// if reason == "" {
// buf.WriteString(`Doesn't match schema "`)
// buf.WriteString(err.SchemaField)
// buf.WriteString(`"`)
// } else {
// buf.WriteString(reason)
// }
// if !SchemaErrorDetailsDisabled {
// buf.WriteString("\nSchema:\n ")
// encoder := json.NewEncoder(buf)
// encoder.SetIndent(" ", " ")
// if err := encoder.Encode(err.Schema); err != nil {
// panic(err)
// }
// buf.WriteString("\nValue:\n ")
// if err := encoder.Encode(err.Value); err != nil {
// panic(err)
// }
// }
// return buf.String()
// }

// func isSliceOfUniqueItems(xs []interface{}) bool {
// s := len(xs)
// m := make(map[string]struct{}, s)
// for _, x := range xs {
// // The input slice is coverted from a JSON string, there shall
// // have no error when covert it back.
// key, _ := json.Marshal(&x)
// m[string(key)] = struct{}{}
// }
// return s == len(m)
// }

// // SliceUniqueItemsChecker is an function used to check if an given slice
// // have unique items.
// type SliceUniqueItemsChecker func(items []interface{}) bool

// // By default using predefined func isSliceOfUniqueItems which make use of
// // json.Marshal to generate a key for map used to check if a given slice
// // have unique items.
// var sliceUniqueItemsChecker SliceUniqueItemsChecker = isSliceOfUniqueItems

// // RegisterArrayUniqueItemsChecker is used to register a customized function
// // used to check if JSON array have unique items.
// func RegisterArrayUniqueItemsChecker(fn SliceUniqueItemsChecker) {
// sliceUniqueItemsChecker = fn
// }

// func unsupportedFormat(format string) error {
// return fmt.Errorf("unsupported 'format' value %q", format)
// }
func (value *Schema) Validate(ctx context.Context) error {
return value.validate(ctx, []*Schema{})
}
13 changes: 8 additions & 5 deletions openapi3/schema_formats.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build legacy

package openapi3

import (
Expand All @@ -6,11 +8,6 @@ import (
"regexp"
)

const (
// FormatOfStringForUUIDOfRFC4122 is an optional predefined format for UUID v1-v5 as specified by RFC4122
FormatOfStringForUUIDOfRFC4122 = `^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`
)

//FormatCallback custom check on exotic formats
type FormatCallback func(Val string) error

Expand Down Expand Up @@ -103,3 +100,9 @@ func DefineIPv4Format() {
func DefineIPv6Format() {
DefineStringFormatCallback("ipv6", validateIPv6)
}

// DefineUUIDFormat defines a string format for UUID v1-v5 as specified by RFC4122
func DefineUUIDFormat() {
const FormatOfStringForUUIDOfRFC4122 = `^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`
DefineStringFormat("uuid", FormatOfStringForUUIDOfRFC4122)
}
52 changes: 52 additions & 0 deletions openapi3/schema_formats_xeipuuv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// +build xeipuuv

package openapi3

import (
"regexp"

"github.com/xeipuuv/gojsonschema"
// https://github.com/xeipuuv/gojsonschema/pull/297/files discriminator support
)

func init() {
// gojsonschema.FormatCheckers = gojsonschema.FormatCheckerChain{} FIXME https://github.com/xeipuuv/gojsonschema/pull/326
gojsonschema.FormatCheckers.Add("byte", byteFormatChecker{})
gojsonschema.FormatCheckers.Add("date", gojsonschema.DateFormatChecker{})
gojsonschema.FormatCheckers.Add("date-time", gojsonschema.DateTimeFormatChecker{})
}

type byteFormatChecker struct{}

var _ gojsonschema.FormatChecker = (*byteFormatChecker)(nil)
var reByteFormatChecker = regexp.MustCompile(`(^$|^[a-zA-Z0-9+/\-_]*=*$)`)

// IsFormat supports base64 and base64url. Padding ('=') is supported.
func (byteFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
if !ok {
return true
}

return reByteFormatChecker.MatchString(asString)
}

// DefineEmailFormat opts-in to checking email format (outside of OpenAPIv3 spec)
func DefineEmailFormat() {
gojsonschema.FormatCheckers.Add("email", gojsonschema.EmailFormatChecker{})
}

// DefineUUIDFormat opts-in to checking uuid format v1-v5 as specified by RFC4122 (outside of OpenAPIv3 spec)
func DefineUUIDFormat() {
gojsonschema.FormatCheckers.Add("uuid", gojsonschema.UUIDFormatChecker{})
}

// DefineIPv4Format opts in ipv4 format validation on top of OAS 3 spec
func DefineIPv4Format() {
gojsonschema.FormatCheckers.Add("ipv4", gojsonschema.IPV4FormatChecker{})
}

// DefineIPv6Format opts in ipv6 format validation on top of OAS 3 spec
func DefineIPv6Format() {
gojsonschema.FormatCheckers.Add("ipv6", gojsonschema.IPV6FormatChecker{})
}
Loading

0 comments on commit e707429

Please sign in to comment.