mirror of
https://github.com/davidebianchi/gswagger.git
synced 2026-01-03 04:38:33 -05:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24dfb293ea | ||
|
|
a5b9bd3dc4 | ||
|
|
7f7c92eaca | ||
|
|
9fac38a162 | ||
|
|
424779a7d8 | ||
|
|
d6a528ea28 | ||
|
|
909c58608a | ||
|
|
43c6e37a47 | ||
|
|
b9dc8ff83c | ||
|
|
1b95853d11 | ||
|
|
e8369933fc | ||
|
|
89d668771a | ||
|
|
0039a3f74f | ||
|
|
b29887d15f | ||
|
|
e03aeb51c2 | ||
|
|
a3cb8e3775 | ||
|
|
995c3d97a2 | ||
|
|
d376b5411e | ||
|
|
b187bd716f | ||
|
|
d07b9c96f5 | ||
|
|
3c8cffc622 |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 0.6.0 - 04-11-2022
|
||||
|
||||
### Added
|
||||
|
||||
- Tags support to `router.AddRoute` accepted definition
|
||||
|
||||
## 0.5.1 - 03-10-2022
|
||||
|
||||
### Fixed
|
||||
|
||||
- upgrade deps
|
||||
|
||||
## v0.5.0 - 05-08-2022
|
||||
|
||||
### Added
|
||||
|
||||
- path params are auto generated if not set
|
||||
|
||||
## v0.4.0 - 02-08-2022
|
||||
|
||||
### Changed
|
||||
|
||||
24
Makefile
Normal file
24
Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
VERSION ?= latest
|
||||
|
||||
# Create a variable that contains the current date in UTC
|
||||
# Different flow if this script is running on Darwin or Linux machines.
|
||||
ifeq (Darwin,$(shell uname))
|
||||
NOW_DATE = $(shell date -u +%d-%m-%Y)
|
||||
else
|
||||
NOW_DATE = $(shell date -u -I)
|
||||
endif
|
||||
|
||||
all: test
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test ./... -coverprofile coverage.out
|
||||
$(MAKE) clean
|
||||
|
||||
.PHONY: version
|
||||
version:
|
||||
sed -i.bck "s|## Unreleased|## Unreleased\n\n## ${VERSION} - ${NOW_DATE}|g" "CHANGELOG.md"
|
||||
rm -fr "CHANGELOG.md.bck"
|
||||
git add "CHANGELOG.md"
|
||||
git commit -m "Upgrade version to v${VERSION}"
|
||||
git tag v${VERSION}
|
||||
32
README.md
32
README.md
@@ -101,7 +101,37 @@ operation.AddRequestBody(requestBody)
|
||||
router.AddRawRoute(http.MethodPost, "/cars", okHandler, operation)
|
||||
```
|
||||
|
||||
This configuration will output the schema shown [here](testdata/users_employees.json)
|
||||
This configuration will output the schema shown [here](testdata/users_employees.json).
|
||||
|
||||
## Auto generated path params schema
|
||||
|
||||
The path params, if not set in schema, are auto generated from the path. Currently, it is supported only the path params like `{myPath}`.
|
||||
|
||||
For example, with this use case:
|
||||
|
||||
```golang
|
||||
okHandler := func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
_, err := router.AddRoute(http.MethodGet, "/users/{userId}", okHandler, Definitions{
|
||||
Querystring: ParameterValue{
|
||||
"query": {
|
||||
Schema: &Schema{Value: ""},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = router.AddRoute(http.MethodGet, "/cars/{carId}/drivers/{driverId}", okHandler, Definitions{})
|
||||
require.NoError(t, err)
|
||||
```
|
||||
|
||||
The generated oas schema will contains `userId`, `carId` and `driverId` as path params set to string.
|
||||
If only one params is set, you must specify manually all the path params.
|
||||
|
||||
The generated file for this test case is [here](./testdata/params-autofill.json).
|
||||
|
||||
## SubRouter
|
||||
|
||||
|
||||
8
go.mod
8
go.mod
@@ -3,13 +3,13 @@ module github.com/davidebianchi/gswagger
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/getkin/kin-openapi v0.98.0
|
||||
github.com/getkin/kin-openapi v0.103.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-openapi/swag v0.21.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/iancoleman/orderedmap v0.2.0 // indirect
|
||||
github.com/invopop/jsonschema v0.5.0
|
||||
github.com/labstack/echo/v4 v4.7.2
|
||||
github.com/invopop/jsonschema v0.6.0
|
||||
github.com/labstack/echo/v4 v4.9.0
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/stretchr/testify v1.8.0
|
||||
)
|
||||
@@ -17,7 +17,7 @@ require (
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/invopop/yaml v0.1.0 // indirect
|
||||
github.com/invopop/yaml v0.2.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/labstack/gommon v0.3.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
|
||||
15
go.sum
15
go.sum
@@ -2,8 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/getkin/kin-openapi v0.98.0 h1:lIACvCG9cxmFsEywz+LCoVhcZHFLUy+Nv5QSkb43eAE=
|
||||
github.com/getkin/kin-openapi v0.98.0/go.mod h1:w4lRPHiyOdwGbOkLIyk+P0qCwlu7TXPCHD/64nSXzgE=
|
||||
github.com/getkin/kin-openapi v0.103.0 h1:F5wAtaQvPWxKCAYZ69LgHAThgu16p4u41VQtbn1U8LA=
|
||||
github.com/getkin/kin-openapi v0.103.0/go.mod h1:w4lRPHiyOdwGbOkLIyk+P0qCwlu7TXPCHD/64nSXzgE=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
@@ -17,10 +17,11 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
|
||||
github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
|
||||
github.com/invopop/jsonschema v0.5.0 h1:6tvpBcwTGxzvx3M9f3IfzqQVyZvoH+0NRUtBcsgyfrU=
|
||||
github.com/invopop/jsonschema v0.5.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
|
||||
github.com/invopop/jsonschema v0.6.0 h1:8e+xY8ZEn8gDHUYylSlLHy22P+SLeIRIHv3nM3hCbmY=
|
||||
github.com/invopop/jsonschema v0.6.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
|
||||
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -28,8 +29,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI=
|
||||
github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
|
||||
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
|
||||
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
|
||||
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
|
||||
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
|
||||
32
route.go
32
route.go
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/davidebianchi/gswagger/apirouter"
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
@@ -54,14 +55,16 @@ type Schema struct {
|
||||
AllowAdditionalProperties bool
|
||||
}
|
||||
|
||||
// ParameterValue is the struct containing the schema or the content information.
|
||||
// If content is specified, it takes precedence.
|
||||
type ParameterValue map[string]struct {
|
||||
type Parameter struct {
|
||||
Content Content
|
||||
Schema *Schema
|
||||
Description string
|
||||
}
|
||||
|
||||
// ParameterValue is the struct containing the schema or the content information.
|
||||
// If content is specified, it takes precedence.
|
||||
type ParameterValue map[string]Parameter
|
||||
|
||||
// ContentValue is the struct containing the content information.
|
||||
type ContentValue struct {
|
||||
Content Content
|
||||
@@ -70,6 +73,7 @@ type ContentValue struct {
|
||||
|
||||
// Definitions of the route.
|
||||
type Definitions struct {
|
||||
Tags []string
|
||||
PathParams ParameterValue
|
||||
Querystring ParameterValue
|
||||
Headers ParameterValue
|
||||
@@ -89,6 +93,7 @@ const (
|
||||
func (r Router) AddRoute(method string, path string, handler apirouter.HandlerFunc, schema Definitions) (interface{}, error) {
|
||||
operation := NewOperation()
|
||||
operation.Responses = make(openapi3.Responses)
|
||||
operation.Tags = schema.Tags
|
||||
|
||||
err := r.resolveRequestBodySchema(schema.RequestBody, operation)
|
||||
if err != nil {
|
||||
@@ -100,7 +105,7 @@ func (r Router) AddRoute(method string, path string, handler apirouter.HandlerFu
|
||||
return nil, fmt.Errorf("%w: %s", ErrResponses, err)
|
||||
}
|
||||
|
||||
err = r.resolveParameterSchema(pathParamsType, schema.PathParams, operation)
|
||||
err = r.resolveParameterSchema(pathParamsType, getPathParamsAutofilled(schema, path), operation)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", ErrPathParams, err)
|
||||
}
|
||||
@@ -255,3 +260,22 @@ func (r Router) addContentToOASSchema(content Content) (openapi3.Content, error)
|
||||
}
|
||||
return oasContent, nil
|
||||
}
|
||||
|
||||
func getPathParamsAutofilled(schema Definitions, path string) ParameterValue {
|
||||
if schema.PathParams == nil {
|
||||
pathParams := strings.Split(path, "/")
|
||||
for _, param := range pathParams {
|
||||
if strings.HasPrefix(param, "{") && strings.HasSuffix(param, "}") {
|
||||
if schema.PathParams == nil {
|
||||
schema.PathParams = make(ParameterValue)
|
||||
}
|
||||
param = strings.Replace(param, "{", "", 1)
|
||||
param = strings.Replace(param, "}", "", 1)
|
||||
schema.PathParams[param] = Parameter{
|
||||
Schema: &Schema{Value: ""},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return schema.PathParams
|
||||
}
|
||||
|
||||
@@ -184,6 +184,24 @@ func TestAddRoutes(t *testing.T) {
|
||||
testPath: "/users/12",
|
||||
fixturesPath: "testdata/params.json",
|
||||
},
|
||||
{
|
||||
name: "schema without params autofilled",
|
||||
routes: func(t *testing.T, router *Router) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/users/{userId}", okHandler, Definitions{
|
||||
Querystring: ParameterValue{
|
||||
"query": {
|
||||
Schema: &Schema{Value: ""},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = router.AddRoute(http.MethodGet, "/cars/{carId}/drivers/{driverId}", okHandler, Definitions{})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
testPath: "/users/12",
|
||||
fixturesPath: "testdata/params-autofill.json",
|
||||
},
|
||||
{
|
||||
name: "schema with querystring",
|
||||
routes: func(t *testing.T, router *Router) {
|
||||
@@ -404,6 +422,17 @@ func TestAddRoutes(t *testing.T) {
|
||||
testMethod: http.MethodPost,
|
||||
fixturesPath: "testdata/oneOf.json",
|
||||
},
|
||||
{
|
||||
name: "schema with tags",
|
||||
routes: func(t *testing.T, router *Router) {
|
||||
_, err := router.AddRoute(http.MethodGet, "/users", okHandler, Definitions{
|
||||
Tags: []string{"Tag1", "Tag2"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
testPath: "/users",
|
||||
fixturesPath: "testdata/tags.json",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
63
testdata/params-autofill.json
vendored
Normal file
63
testdata/params-autofill.json
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"components": {},
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/cars/{carId}/drivers/{driverId}": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "carId",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "driverId",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{userId}": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "userId",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
testdata/tags.json
vendored
Normal file
20
testdata/tags.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"components": {},
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"tags": ["Tag1", "Tag2"],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user