mirror of
https://github.com/davidebianchi/gswagger.git
synced 2025-12-23 23:38:43 -05:00
Merge pull request #112 from davidebianchi/add-new-oas-fields-to-definition
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- add new fields to Definition:
|
||||
- Security
|
||||
- Tags
|
||||
- Summary
|
||||
- Description
|
||||
- Deprecated
|
||||
- Extensions
|
||||
|
||||
### Updated
|
||||
|
||||
- update kin-openapi to 0.114.0: this change removes components from exposed oas (if not manually set). In this update of kin-openapi, there is a breaking change with the T struct, which now accepts component as pointer.
|
||||
|
||||
@@ -37,3 +37,12 @@ func (o *Operation) AddResponse(status int, response *openapi3.Response) {
|
||||
}
|
||||
o.Operation.AddResponse(status, response)
|
||||
}
|
||||
|
||||
func (o *Operation) addSecurityRequirements(securityRequirements SecurityRequirements) {
|
||||
if securityRequirements != nil && o.Security == nil {
|
||||
o.Security = openapi3.NewSecurityRequirements()
|
||||
}
|
||||
for _, securityRequirement := range securityRequirements {
|
||||
o.Security.With(openapi3.SecurityRequirement(securityRequirement))
|
||||
}
|
||||
}
|
||||
|
||||
31
route.go
31
route.go
@@ -71,15 +71,42 @@ type ContentValue struct {
|
||||
Description string
|
||||
}
|
||||
|
||||
type SecurityRequirements []SecurityRequirement
|
||||
type SecurityRequirement map[string][]string
|
||||
|
||||
// Definitions of the route.
|
||||
// To see how to use, refer to https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md
|
||||
type Definitions struct {
|
||||
// Specification extensions https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specification-extensions
|
||||
Extensions map[string]interface{}
|
||||
// Optional field for documentation
|
||||
Tags []string
|
||||
Summary string
|
||||
Description string
|
||||
Deprecated bool
|
||||
|
||||
// PathParams contains the path parameters. If empty is autocompleted from the path
|
||||
PathParams ParameterValue
|
||||
Querystring ParameterValue
|
||||
Headers ParameterValue
|
||||
Cookies ParameterValue
|
||||
RequestBody *ContentValue
|
||||
Responses map[int]ContentValue
|
||||
|
||||
Security SecurityRequirements
|
||||
}
|
||||
|
||||
func newOperationFromDefinition(schema Definitions) Operation {
|
||||
operation := NewOperation()
|
||||
operation.Responses = make(openapi3.Responses)
|
||||
operation.Tags = schema.Tags
|
||||
operation.Extensions = schema.Extensions
|
||||
operation.addSecurityRequirements(schema.Security)
|
||||
operation.Description = schema.Description
|
||||
operation.Summary = schema.Summary
|
||||
operation.Deprecated = schema.Deprecated
|
||||
|
||||
return operation
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -91,9 +118,7 @@ const (
|
||||
|
||||
// AddRoute add a route with json schema inferred by passed schema.
|
||||
func (r Router[HandlerFunc, Route]) AddRoute(method string, path string, handler HandlerFunc, schema Definitions) (Route, error) {
|
||||
operation := NewOperation()
|
||||
operation.Responses = make(openapi3.Responses)
|
||||
operation.Tags = schema.Tags
|
||||
operation := newOperationFromDefinition(schema)
|
||||
|
||||
err := r.resolveRequestBodySchema(schema.RequestBody, operation)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,7 +20,6 @@ const formDataType = "multipart/form-data"
|
||||
type TestRouter = Router[gorilla.HandlerFunc, gorilla.Route]
|
||||
|
||||
func TestAddRoutes(t *testing.T) {
|
||||
|
||||
type User struct {
|
||||
Name string `json:"name" jsonschema:"title=The user name,required" jsonschema_extras:"example=Jane"`
|
||||
PhoneNumber int `json:"phone" jsonschema:"title=mobile number of user"`
|
||||
@@ -435,6 +434,66 @@ func TestAddRoutes(t *testing.T) {
|
||||
testPath: "/users",
|
||||
fixturesPath: "testdata/tags.json",
|
||||
},
|
||||
{
|
||||
name: "schema with security",
|
||||
routes: func(t *testing.T, router *TestRouter) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/users", okHandler, Definitions{
|
||||
Security: SecurityRequirements{
|
||||
SecurityRequirement{
|
||||
"api_key": []string{},
|
||||
"auth": []string{
|
||||
"resource.write",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
testPath: "/users",
|
||||
fixturesPath: "testdata/security.json",
|
||||
},
|
||||
{
|
||||
name: "schema with extension",
|
||||
routes: func(t *testing.T, router *TestRouter) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/users", okHandler, Definitions{
|
||||
Extensions: map[string]interface{}{
|
||||
"x-extension-field": map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
testPath: "/users",
|
||||
fixturesPath: "testdata/extension.json",
|
||||
},
|
||||
{
|
||||
name: "invalid extension - not starts with x-",
|
||||
routes: func(t *testing.T, router *TestRouter) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/", okHandler, Definitions{
|
||||
Extensions: map[string]interface{}{
|
||||
"extension-field": map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
})
|
||||
require.EqualError(t, err, "extra sibling fields: [extension-field]")
|
||||
},
|
||||
fixturesPath: "testdata/empty.json",
|
||||
},
|
||||
{
|
||||
name: "schema with summary, description, deprecated and operationID",
|
||||
routes: func(t *testing.T, router *TestRouter) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/users", okHandler, Definitions{
|
||||
Summary: "small description",
|
||||
Description: "this is the long route description",
|
||||
Deprecated: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
testPath: "/users",
|
||||
fixturesPath: "testdata/users-deprecated-with-description.json",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
21
testdata/extension.json
vendored
Normal file
21
testdata/extension.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"x-extension-field": {
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
testdata/security.json
vendored
Normal file
26
testdata/security.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"api_key": [],
|
||||
"auth": [
|
||||
"resource.write"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
testdata/users-deprecated-with-description.json
vendored
Normal file
21
testdata/users-deprecated-with-description.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"description": "this is the long route description",
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"summary": "small description"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user