Skip to content

Commit

Permalink
openapi3: add support for extensions on the few types left
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com>
  • Loading branch information
fenollp committed Nov 28, 2023
1 parent 0cc5e22 commit 9ea6694
Show file tree
Hide file tree
Showing 42 changed files with 1,213 additions and 330 deletions.
151 changes: 134 additions & 17 deletions .github/docs/openapi3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,46 @@ func (addProps AdditionalProperties) MarshalJSON() ([]byte, error)
func (addProps *AdditionalProperties) UnmarshalJSON(data []byte) error
UnmarshalJSON sets AdditionalProperties to a copy of data.

type Callback map[string]*PathItem
type Callback struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`

// Has unexported fields.
}
Callback is specified by OpenAPI/Swagger standard version 3. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#callback-object

func (callback Callback) Validate(ctx context.Context, opts ...ValidationOption) error
func NewCallback(opts ...NewCallbackOption) *Callback
NewCallback builds a Callback object with path items in insertion order.

func NewCallbackWithCapacity(cap int) *Callback
NewCallbackWithCapacity builds a Callback object of the given capacity.

func (callback Callback) JSONLookup(token string) (interface{}, error)
JSONLookup implements
https://github.com/go-openapi/jsonpointer#JSONPointable

func (callback *Callback) Len() int
Len returns the amount of keys in callback excluding callback.Extensions.

func (callback *Callback) Map() map[string]*PathItem
Map returns callback as a 'map'. Note: iteration on Go maps is not ordered.

func (callback Callback) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of Callback.

func (callback *Callback) Set(key string, value *PathItem)
Set adds or replaces key 'key' of 'callback' with 'value'. Note: 'callback'
MUST be non-nil

func (callback *Callback) UnmarshalJSON(data []byte) (err error)
UnmarshalJSON sets Callback to a copy of data.

func (callback *Callback) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if Callback does not comply with the OpenAPI spec.

func (callback *Callback) Value(key string) *PathItem
Value returns the callback for key or nil

type CallbackRef struct {
Ref string
Value *Callback
Expand Down Expand Up @@ -609,6 +642,27 @@ func (me MultiError) Is(target error) bool
`errors.Is()` It will also return true if any of the contained errors match
target

type NewCallbackOption func(*Callback)
NewCallbackOption describes options to NewCallback func

func WithCallback(cb string, pathItem *PathItem) NewCallbackOption
WithCallback adds Callback as an option to NewCallback

type NewPathsOption func(*Paths)
NewPathsOption describes options to NewPaths func

func WithPath(path string, pathItem *PathItem) NewPathsOption
WithPath adds a named path item

type NewResponsesOption func(*Responses)
NewResponsesOption describes options to NewResponses func

func WithName(name string, response *Response) NewResponsesOption
WithName adds a name-keyed Response

func WithStatus(status int, responseRef *ResponseRef) NewResponsesOption
WithStatus adds a status code keyed ResponseRef

type OAuthFlow struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`

Expand Down Expand Up @@ -673,7 +727,7 @@ type Operation struct {
RequestBody *RequestBodyRef `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`

// Responses.
Responses Responses `json:"responses" yaml:"responses"` // Required
Responses *Responses `json:"responses" yaml:"responses"` // Required

// Optional callbacks
Callbacks Callbacks `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
Expand Down Expand Up @@ -847,11 +901,21 @@ func (pathItem *PathItem) UnmarshalJSON(data []byte) error
func (pathItem *PathItem) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if PathItem does not comply with the OpenAPI spec.

type Paths map[string]*PathItem
type Paths struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`

// Has unexported fields.
}
Paths is specified by OpenAPI/Swagger standard version 3. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object

func (paths Paths) Find(key string) *PathItem
func NewPaths(opts ...NewPathsOption) *Paths
NewPaths builds a paths object with path items in insertion order.

func NewPathsWithCapacity(cap int) *Paths
NewPathsWithCapacity builds a paths object of the given capacity.

func (paths *Paths) Find(key string) *PathItem
Find returns a path that matches the key.

The method ignores differences in template variable names (except possible
Expand All @@ -866,16 +930,39 @@ func (paths Paths) Find(key string) *PathItem

would return the correct path item.

func (paths Paths) InMatchingOrder() []string
func (paths *Paths) InMatchingOrder() []string
InMatchingOrder returns paths in the
order they are matched against URLs. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#paths-object
When matching URLs, concrete (non-templated) paths would be matched before
their templated counterparts.

func (paths Paths) Validate(ctx context.Context, opts ...ValidationOption) error
func (paths Paths) JSONLookup(token string) (interface{}, error)
JSONLookup implements
https://github.com/go-openapi/jsonpointer#JSONPointable

func (paths *Paths) Len() int
Len returns the amount of keys in paths excluding paths.Extensions.

func (paths *Paths) Map() map[string]*PathItem
Map returns paths as a 'map'. Note: iteration on Go maps is not ordered.

func (paths Paths) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of Paths.

func (paths *Paths) Set(key string, value *PathItem)
Set adds or replaces key 'key' of 'paths' with 'value'. Note: 'paths' MUST
be non-nil

func (paths *Paths) UnmarshalJSON(data []byte) (err error)
UnmarshalJSON sets Paths to a copy of data.

func (paths *Paths) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if Paths does not comply with the OpenAPI spec.

func (paths *Paths) Value(key string) *PathItem
Value returns the paths for key or nil

type ReadFromURIFunc func(loader *Loader, url *url.URL) ([]byte, error)
ReadFromURIFunc defines a function which reads the contents of a resource
located at a URI.
Expand Down Expand Up @@ -1039,28 +1126,58 @@ func (x *ResponseRef) Validate(ctx context.Context, opts ...ValidationOption) er
Validate returns an error if ResponseRef does not comply with the OpenAPI
spec.

type Responses map[string]*ResponseRef
type Responses struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`

// Has unexported fields.
}
Responses is specified by OpenAPI/Swagger 3.0 standard. See
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responses-object

func NewResponses() Responses
func NewResponses(opts ...NewResponsesOption) *Responses
NewResponses builds a responses object with response objects in insertion
order. Given no arguments, NewResponses returns a valid responses object
containing a default match-all reponse.

func (responses Responses) Default() *ResponseRef
func NewResponsesWithCapacity(cap int) *Responses
NewResponsesWithCapacity builds a responses object of the given capacity.

func (responses Responses) Get(status int) *ResponseRef
Get returns a ResponseRef for the given status If an exact
func (responses *Responses) Default() *ResponseRef
Default returns the default response

func (responses Responses) JSONLookup(token string) (interface{}, error)
JSONLookup implements
https://github.com/go-openapi/jsonpointer#JSONPointable

func (responses *Responses) Len() int
Len returns the amount of keys in responses excluding responses.Extensions.

func (responses *Responses) Map() map[string]*ResponseRef
Map returns responses as a 'map'. Note: iteration on Go maps is not ordered.

func (responses Responses) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of Responses.

func (responses *Responses) Set(key string, value *ResponseRef)
Set adds or replaces key 'key' of 'responses' with 'value'. Note:
'responses' MUST be non-nil

func (responses *Responses) Status(status int) *ResponseRef
Status returns a ResponseRef for the given status If an exact
match isn't initially found a patterned field is checked using
the first digit to determine the range (eg: 201 to 2XX) See
https://spec.openapis.org/oas/v3.0.3#patterned-fields-0

func (responses Responses) JSONLookup(token string) (interface{}, error)
JSONLookup implements
https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (responses *Responses) UnmarshalJSON(data []byte) (err error)
UnmarshalJSON sets Responses to a copy of data.

func (responses Responses) Validate(ctx context.Context, opts ...ValidationOption) error
func (responses *Responses) Validate(ctx context.Context, opts ...ValidationOption) error
Validate returns an error if Responses does not comply with the OpenAPI
spec.

func (responses *Responses) Value(key string) *ResponseRef
Value returns the responses for key or nil

type Schema struct {
Extensions map[string]interface{} `json:"-" yaml:"-"`

Expand Down Expand Up @@ -1519,7 +1636,7 @@ type T struct {
OpenAPI string `json:"openapi" yaml:"openapi"` // Required
Components *Components `json:"components,omitempty" yaml:"components,omitempty"`
Info *Info `json:"info" yaml:"info"` // Required
Paths Paths `json:"paths" yaml:"paths"` // Required
Paths *Paths `json:"paths" yaml:"paths"` // Required
Security SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"`
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ jobs:

- uses: actions/checkout@v2

- name: Check codegen
run: |
./refs.sh | tee openapi3/refs.go
git --no-pager diff --exit-code
- run: ./refs.sh | tee openapi3/refs.go
- run: git --no-pager diff --exit-code

- run: ./maps.sh
- run: git --no-pager diff --exit-code

- name: Check docsgen
run: ./docs.sh
- run: ./docs.sh

- run: go mod download && go mod tidy && go mod verify
- run: git --no-pager diff --exit-code
Expand Down Expand Up @@ -119,7 +119,7 @@ jobs:
- if: runner.os == 'Linux'
name: Ensure non-pointer MarshalJSON
run: |
! git grep -InE 'func.+[*].+[)].MarshalJSON[(][)]'
! git grep -InE 'func[^{}]+[*][^{}]+[)].MarshalJSON[(][)]'
- if: runner.os == 'Linux'
name: Use `loader := NewLoader(); loader.Load ...`
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ go run github.com/getkin/kin-openapi/cmd/validate@latest [--circular] [--default
Use `openapi3.Loader`, which resolves all references:
```go
loader := openapi3.NewLoader()
doc, err := loader.LoadFromFile("swagger.json")
doc, err := loader.LoadFromFile("my-openapi-spec.json")
```

## Getting OpenAPI operation that matches request
Expand Down Expand Up @@ -275,7 +275,15 @@ func safeErrorMessage(err *openapi3.SchemaError) string {

This will change the schema validation errors to return only the `Reason` field, which is guaranteed to not include the original value.

## CHANGELOG: Sub-v0 breaking API changes
## CHANGELOG: Sub-v1 breaking API changes

### v0.122.0
* `Paths` field of `openapi3.T` is now a pointer
* `Responses` field of `openapi3.Operation` is now a pointer
* `openapi3.Paths` went from `map[string]*PathItem` to a struct with an `Extensions` field and methods: `Set`, `Value`, `Len`, `Map`, and `New*`.
* `openapi3.Callback` went from `map[string]*PathItem` to a struct with an `Extensions` field and methods: `Set`, `Value`, `Len`, `Map`, and `New*`.
* `openapi3.Responses` went from `map[string]*ResponseRef` to a struct with an `Extensions` field and methods: `Set`, `Value`, `Len`, `Map`, and `New*`.
* `(openapi3.Responses).Get(int)` renamed to `(*openapi3.Responses).Status(int)`

### v0.121.0
* Introduce `openapi3.RequestBodies` (an alias on `map[string]*openapi3.ResponseRef`) and use it in place of `openapi3.Responses` for field `openapi3.Components.Responses`.
Expand Down

0 comments on commit 9ea6694

Please sign in to comment.