refactor: rename swagger to oas in errors (#165)

This commit is contained in:
Federico Maggi
2024-11-08 19:52:34 +01:00
committed by GitHub
parent 3563d41c0f
commit eb3c4d9c98
31 changed files with 141 additions and 132 deletions

View File

@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Refactor
- renamed swagger to openapi in error messages
## 0.10.0 - 28-02-2024
### BREAKING CHANGES

61
main.go
View File

@@ -13,21 +13,26 @@ import (
)
var (
// ErrGenerateSwagger throws when fails the marshalling of the swagger struct.
ErrGenerateSwagger = errors.New("fail to generate swagger")
// ErrValidatingSwagger throws when given swagger params are not correct.
ErrValidatingSwagger = errors.New("fails to validate swagger")
// ErrGenerateOAS throws when fails the marshalling of the swagger struct.
ErrGenerateOAS = errors.New("fail to generate openapi")
// ErrValidatingOAS throws when given openapi params are not correct.
ErrValidatingOAS = errors.New("fails to validate openapi")
// Deprecated: ErrGenerateSwagger has been deprecated, use ErrGenerateOAS instead.
ErrGenerateSwagger = ErrGenerateOAS
// Deprecated: ErrValidatingSwagger has been deprecated, use ErrValidatingOAS instead.
ErrValidatingSwagger = ErrValidatingOAS
)
const (
// DefaultJSONDocumentationPath is the path of the swagger documentation in json format.
// DefaultJSONDocumentationPath is the path of the openapi documentation in json format.
DefaultJSONDocumentationPath = "/documentation/json"
// DefaultYAMLDocumentationPath is the path of the swagger documentation in yaml format.
// DefaultYAMLDocumentationPath is the path of the openapi documentation in yaml format.
DefaultYAMLDocumentationPath = "/documentation/yaml"
defaultOpenapiVersion = "3.0.0"
)
// Router handle the api router and the swagger schema.
// Router handle the api router and the openapi schema.
// api router supported out of the box are:
// - gorilla mux
type Router[HandlerFunc, Route any] struct {
@@ -51,11 +56,11 @@ type Options struct {
PathPrefix string
}
// NewRouter generate new router with swagger. Default to OpenAPI 3.0.0
// NewRouter generate new router with openapi. Default to OpenAPI 3.0.0
func NewRouter[HandlerFunc, Route any](router apirouter.Router[HandlerFunc, Route], options Options) (*Router[HandlerFunc, Route], error) {
swagger, err := generateNewValidOpenapi(options.Openapi)
openapi, err := generateNewValidOpenapi(options.Openapi)
if err != nil {
return nil, fmt.Errorf("%w: %s", ErrValidatingSwagger, err)
return nil, fmt.Errorf("%w: %s", ErrValidatingOAS, err)
}
var ctx = options.Context
@@ -81,7 +86,7 @@ func NewRouter[HandlerFunc, Route any](router apirouter.Router[HandlerFunc, Rout
return &Router[HandlerFunc, Route]{
router: router,
swaggerSchema: swagger,
swaggerSchema: openapi,
context: ctx,
yamlDocumentationPath: yamlDocumentationPath,
jsonDocumentationPath: jsonDocumentationPath,
@@ -104,46 +109,46 @@ func (r Router[HandlerFunc, Route]) SubRouter(router apirouter.Router[HandlerFun
}, nil
}
func generateNewValidOpenapi(swagger *openapi3.T) (*openapi3.T, error) {
if swagger == nil {
return nil, fmt.Errorf("swagger is required")
func generateNewValidOpenapi(openapi *openapi3.T) (*openapi3.T, error) {
if openapi == nil {
return nil, fmt.Errorf("openapi is required")
}
if swagger.OpenAPI == "" {
swagger.OpenAPI = defaultOpenapiVersion
if openapi.OpenAPI == "" {
openapi.OpenAPI = defaultOpenapiVersion
}
if swagger.Paths == nil {
swagger.Paths = &openapi3.Paths{}
if openapi.Paths == nil {
openapi.Paths = &openapi3.Paths{}
}
if swagger.Info == nil {
return nil, fmt.Errorf("swagger info is required")
if openapi.Info == nil {
return nil, fmt.Errorf("openapi info is required")
}
if swagger.Info.Title == "" {
return nil, fmt.Errorf("swagger info title is required")
if openapi.Info.Title == "" {
return nil, fmt.Errorf("openapi info title is required")
}
if swagger.Info.Version == "" {
return nil, fmt.Errorf("swagger info version is required")
if openapi.Info.Version == "" {
return nil, fmt.Errorf("openapi info version is required")
}
return swagger, nil
return openapi, nil
}
// GenerateAndExposeOpenapi creates a /documentation/json route on router and
// expose the generated swagger
func (r Router[_, _]) GenerateAndExposeOpenapi() error {
if err := r.swaggerSchema.Validate(r.context); err != nil {
return fmt.Errorf("%w: %s", ErrValidatingSwagger, err)
return fmt.Errorf("%w: %s", ErrValidatingOAS, err)
}
jsonSwagger, err := r.swaggerSchema.MarshalJSON()
if err != nil {
return fmt.Errorf("%w json marshal: %s", ErrGenerateSwagger, err)
return fmt.Errorf("%w json marshal: %s", ErrGenerateOAS, err)
}
r.router.AddRoute(http.MethodGet, r.jsonDocumentationPath, r.router.SwaggerHandler("application/json", jsonSwagger))
yamlSwagger, err := yaml.JSONToYAML(jsonSwagger)
if err != nil {
return fmt.Errorf("%w yaml marshal: %s", ErrGenerateSwagger, err)
return fmt.Errorf("%w yaml marshal: %s", ErrGenerateOAS, err)
}
r.router.AddRoute(http.MethodGet, r.yamlDocumentationPath, r.router.SwaggerHandler("text/plain", yamlSwagger))

View File

@@ -33,7 +33,7 @@ func TestNewRouter(t *testing.T) {
r, err := NewRouter(mAPIRouter, Options{})
require.Nil(t, r)
require.EqualError(t, err, fmt.Sprintf("%s: swagger is required", ErrValidatingSwagger))
require.EqualError(t, err, fmt.Sprintf("%s: openapi is required", ErrValidatingOAS))
})
t.Run("ok - with default context", func(t *testing.T) {
@@ -119,50 +119,50 @@ func TestNewRouter(t *testing.T) {
}
func TestGenerateValidSwagger(t *testing.T) {
t.Run("not ok - empty swagger info", func(t *testing.T) {
swagger := &openapi3.T{}
t.Run("not ok - empty openapi info", func(t *testing.T) {
openapi := &openapi3.T{}
swagger, err := generateNewValidOpenapi(swagger)
require.Nil(t, swagger)
require.EqualError(t, err, "swagger info is required")
openapi, err := generateNewValidOpenapi(openapi)
require.Nil(t, openapi)
require.EqualError(t, err, "openapi info is required")
})
t.Run("not ok - empty info title", func(t *testing.T) {
swagger := &openapi3.T{
openapi := &openapi3.T{
Info: &openapi3.Info{},
}
swagger, err := generateNewValidOpenapi(swagger)
require.Nil(t, swagger)
require.EqualError(t, err, "swagger info title is required")
openapi, err := generateNewValidOpenapi(openapi)
require.Nil(t, openapi)
require.EqualError(t, err, "openapi info title is required")
})
t.Run("not ok - empty info version", func(t *testing.T) {
swagger := &openapi3.T{
openapi := &openapi3.T{
Info: &openapi3.Info{
Title: "title",
},
}
swagger, err := generateNewValidOpenapi(swagger)
require.Nil(t, swagger)
require.EqualError(t, err, "swagger info version is required")
openapi, err := generateNewValidOpenapi(openapi)
require.Nil(t, openapi)
require.EqualError(t, err, "openapi info version is required")
})
t.Run("ok - custom swagger", func(t *testing.T) {
swagger := &openapi3.T{
t.Run("ok - custom openapi", func(t *testing.T) {
openapi := &openapi3.T{
Info: &openapi3.Info{},
}
swagger, err := generateNewValidOpenapi(swagger)
require.Nil(t, swagger)
require.EqualError(t, err, "swagger info title is required")
openapi, err := generateNewValidOpenapi(openapi)
require.Nil(t, openapi)
require.EqualError(t, err, "openapi info title is required")
})
t.Run("not ok - swagger is required", func(t *testing.T) {
swagger, err := generateNewValidOpenapi(nil)
require.Nil(t, swagger)
require.EqualError(t, err, "swagger is required")
t.Run("not ok - openapi is required", func(t *testing.T) {
openapi, err := generateNewValidOpenapi(nil)
require.Nil(t, openapi)
require.EqualError(t, err, "openapi is required")
})
t.Run("ok", func(t *testing.T) {
@@ -170,22 +170,22 @@ func TestGenerateValidSwagger(t *testing.T) {
Title: "my title",
Version: "my version",
}
swagger := &openapi3.T{
openapi := &openapi3.T{
Info: info,
}
swagger, err := generateNewValidOpenapi(swagger)
openapi, err := generateNewValidOpenapi(openapi)
require.NoError(t, err)
require.Equal(t, &openapi3.T{
OpenAPI: defaultOpenapiVersion,
Info: info,
Paths: &openapi3.Paths{},
}, swagger)
}, openapi)
})
}
func TestGenerateAndExposeSwagger(t *testing.T) {
t.Run("fails swagger validation", func(t *testing.T) {
t.Run("fails openapi validation", func(t *testing.T) {
mRouter := mux.NewRouter()
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: &openapi3.T{
@@ -204,17 +204,17 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
err = router.GenerateAndExposeOpenapi()
require.Error(t, err)
require.True(t, strings.HasPrefix(err.Error(), fmt.Sprintf("%s:", ErrValidatingSwagger)))
require.True(t, strings.HasPrefix(err.Error(), fmt.Sprintf("%s:", ErrValidatingOAS)))
})
t.Run("correctly expose json documentation from loaded swagger file", func(t *testing.T) {
t.Run("correctly expose json documentation from loaded openapi file", func(t *testing.T) {
mRouter := mux.NewRouter()
swagger, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
openapi, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
require.NoError(t, err)
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: swagger,
Openapi: openapi,
})
require.NoError(t, err)
@@ -234,14 +234,14 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
require.JSONEq(t, string(actual), body)
})
t.Run("correctly expose json documentation from loaded swagger file - custom path", func(t *testing.T) {
t.Run("correctly expose json documentation from loaded openapi file - custom path", func(t *testing.T) {
mRouter := mux.NewRouter()
swagger, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
openapi, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
require.NoError(t, err)
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: swagger,
Openapi: openapi,
JSONDocumentationPath: "/custom/path",
})
require.NoError(t, err)
@@ -262,14 +262,14 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
require.JSONEq(t, string(actual), body)
})
t.Run("correctly expose yaml documentation from loaded swagger file", func(t *testing.T) {
t.Run("correctly expose yaml documentation from loaded openapi file", func(t *testing.T) {
mRouter := mux.NewRouter()
swagger, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
openapi, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
require.NoError(t, err)
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: swagger,
Openapi: openapi,
})
require.NoError(t, err)
@@ -289,14 +289,14 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
require.YAMLEq(t, string(expected), body, string(body))
})
t.Run("correctly expose yaml documentation from loaded swagger file - custom path", func(t *testing.T) {
t.Run("correctly expose yaml documentation from loaded openapi file - custom path", func(t *testing.T) {
mRouter := mux.NewRouter()
swagger, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
openapi, err := openapi3.NewLoader().LoadFromFile("testdata/users_employees.json")
require.NoError(t, err)
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: swagger,
Openapi: openapi,
YAMLDocumentationPath: "/custom/path",
})
require.NoError(t, err)
@@ -323,8 +323,8 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: &openapi3.T{
Info: &openapi3.Info{
Title: "test swagger title",
Version: "test swagger version",
Title: "test openapi title",
Version: "test openapi version",
},
},
JSONDocumentationPath: "/custom/path",
@@ -402,8 +402,8 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
router, err := NewRouter(gorilla.NewRouter(mRouter), Options{
Openapi: &openapi3.T{
Info: &openapi3.Info{
Title: "test swagger title",
Version: "test swagger version",
Title: "test openapi title",
Version: "test openapi version",
},
},
JSONDocumentationPath: "/custom/path",

View File

@@ -27,7 +27,7 @@ func TestNewOperation(t *testing.T) {
operation.Responses = openapi3.NewResponses()
return operation
},
expectedJSON: `{"info":{"title":"test swagger title","version":"test swagger version"},"openapi":"3.0.0","paths":{"/":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"bar":{"maximum":15,"minimum":5,"type":"integer"},"foo":{"type":"string"}},"type":"object"}}}},"responses":{"default":{"description":""}}}}}}`,
expectedJSON: `{"info":{"title":"test openapi title","version":"test openapi version"},"openapi":"3.0.0","paths":{"/":{"post":{"requestBody":{"content":{"application/json":{"schema":{"properties":{"bar":{"maximum":15,"minimum":5,"type":"integer"},"foo":{"type":"string"}},"type":"object"}}}},"responses":{"default":{"description":""}}}}}}`,
},
{
name: "add response",
@@ -36,19 +36,19 @@ func TestNewOperation(t *testing.T) {
operation.AddResponse(200, response)
return operation
},
expectedJSON: `{"info":{"title":"test swagger title","version":"test swagger version"},"openapi":"3.0.0","paths":{"/":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"bar":{"maximum":15,"minimum":5,"type":"integer"},"foo":{"type":"string"}},"type":"object"}}},"description":""}}}}}}`,
expectedJSON: `{"info":{"title":"test openapi title","version":"test openapi version"},"openapi":"3.0.0","paths":{"/":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"bar":{"maximum":15,"minimum":5,"type":"integer"},"foo":{"type":"string"}},"type":"object"}}},"description":""}}}}}}`,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
swagger := getBaseSwagger(t)
swagger.OpenAPI = "3.0.0"
openapi := getBaseSwagger(t)
openapi.OpenAPI = "3.0.0"
operation := test.getOperation(t, NewOperation())
swagger.AddOperation("/", http.MethodPost, operation.Operation)
openapi.AddOperation("/", http.MethodPost, operation.Operation)
data, _ := swagger.MarshalJSON()
data, _ := openapi.MarshalJSON()
jsonData := string(data)
require.JSONEq(t, test.expectedJSON, jsonData, "actual json data: %s", jsonData)
})

View File

@@ -24,7 +24,7 @@ var (
)
// AddRawRoute add route to router with specific method, path and handler. Add the
// router also to the swagger schema, after validating it
// router also to the openapi schema, after validating it
func (r Router[HandlerFunc, Route]) AddRawRoute(method string, routePath string, handler HandlerFunc, operation Operation) (Route, error) {
op := operation.Operation
if op != nil {

View File

@@ -533,7 +533,7 @@ func TestAddRoutes(t *testing.T) {
require.Equal(t, "OK", body)
}
t.Run("and generate swagger documentation in json", func(t *testing.T) {
t.Run("and generate openapi documentation in json", func(t *testing.T) {
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, DefaultJSONDocumentationPath, nil)
@@ -1116,8 +1116,8 @@ func getBaseSwagger(t *testing.T) *openapi3.T {
return &openapi3.T{
Info: &openapi3.Info{
Title: "test swagger title",
Version: "test swagger version",
Title: "test openapi title",
Version: "test openapi version",
},
}
}

View File

@@ -17,8 +17,8 @@ import (
)
const (
swaggerOpenapiTitle = "test swagger title"
swaggerOpenapiVersion = "test swagger version"
swaggerOpenapiTitle = "test openapi title"
swaggerOpenapiVersion = "test openapi version"
)
type echoSwaggerRouter = swagger.Router[echo.HandlerFunc, *echo.Route]

View File

@@ -19,8 +19,8 @@ import (
type SwaggerRouter = swagger.Router[oasFiber.HandlerFunc, oasFiber.Route]
const (
swaggerOpenapiTitle = "test swagger title"
swaggerOpenapiVersion = "test swagger version"
swaggerOpenapiTitle = "test openapi title"
swaggerOpenapiVersion = "test openapi version"
)
func TestFiberIntegration(t *testing.T) {

View File

@@ -16,8 +16,8 @@ import (
)
const (
swaggerOpenapiTitle = "test swagger title"
swaggerOpenapiVersion = "test swagger version"
swaggerOpenapiTitle = "test openapi title"
swaggerOpenapiVersion = "test openapi version"
)
type SwaggerRouter = swagger.Router[gorilla.HandlerFunc, gorilla.Route]

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/allof.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/anyof.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/empty.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {}

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/oneOf.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/query.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

4
testdata/tags.json vendored
View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,7 +1,7 @@
{
"info": {
"title": "test swagger title",
"version": "test swagger version"
"title": "test openapi title",
"version": "test openapi version"
},
"openapi": "3.0.0",
"paths": {

View File

@@ -1,6 +1,6 @@
info:
title: test swagger title
version: test swagger version
title: test openapi title
version: test openapi version
openapi: 3.0.0
paths:
/employees: