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

openapi3: add support for extensions on the few types left #763

Merged
merged 1 commit into from
Nov 28, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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