mirror of
https://github.com/davidebianchi/gswagger.git
synced 2026-01-10 08:08:45 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffb0e6b3f7 | ||
|
|
94abd8f4bf | ||
|
|
7232d5d823 | ||
|
|
b26ddbeecf | ||
|
|
3374e2bd80 | ||
|
|
33d81e9cdd | ||
|
|
a7a671be5a | ||
|
|
239a70a1a0 | ||
|
|
8c0aacb68c | ||
|
|
d145c6ca5d | ||
|
|
a8c5be8870 | ||
|
|
8fda85d9d3 | ||
|
|
a872dd02b7 |
6
.github/workflows/test-builds.yml
vendored
6
.github/workflows/test-builds.yml
vendored
@@ -26,7 +26,11 @@ jobs:
|
||||
go get -v -t -d ./...
|
||||
- name: Run tests
|
||||
run: |
|
||||
go test ./... -count=1 -race -cover
|
||||
go test ./... -count=1 -race -cover -coverprofile cover.out
|
||||
- name: Build
|
||||
run: |
|
||||
go build -v .
|
||||
- name: Send the coverage output
|
||||
uses: shogo82148/actions-goveralls@v1
|
||||
with:
|
||||
path-to-profile: cover.out
|
||||
|
||||
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## v0.3.0 - 10-11-2021
|
||||
|
||||
### Added
|
||||
|
||||
- handle router with path prefix
|
||||
- add SubRouter method to use a new sub router
|
||||
|
||||
## v0.2.0 - 16-10-2021
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<div align="center">
|
||||
|
||||
|
||||
[![Build Status][github-actions-svg]][github-actions]
|
||||
[](https://coveralls.io/github/davidebianchi/gswagger?branch=main)
|
||||
[![Go Report Card][go-report-card]][go-report-card-link]
|
||||
[![GoDoc][godoc-svg]][godoc-link]
|
||||
|
||||
|
||||
19
main.go
19
main.go
@@ -36,6 +36,7 @@ type Router struct {
|
||||
context context.Context
|
||||
jsonDocumentationPath string
|
||||
yamlDocumentationPath string
|
||||
pathPrefix string
|
||||
}
|
||||
|
||||
// Options to be passed to create the new router and swagger
|
||||
@@ -46,6 +47,8 @@ type Options struct {
|
||||
JSONDocumentationPath string
|
||||
// YAMLDocumentationPath is the path exposed by yaml endpoint. Default to /documentation/yaml.
|
||||
YAMLDocumentationPath string
|
||||
// Add path prefix to add to every router path.
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
// NewRouter generate new router with swagger. Default to OpenAPI 3.0.0
|
||||
@@ -82,6 +85,22 @@ func NewRouter(router apirouter.Router, options Options) (*Router, error) {
|
||||
context: ctx,
|
||||
yamlDocumentationPath: yamlDocumentationPath,
|
||||
jsonDocumentationPath: jsonDocumentationPath,
|
||||
pathPrefix: options.PathPrefix,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type SubRouterOptions struct {
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
func (r Router) SubRouter(router apirouter.Router, opts SubRouterOptions) (*Router, error) {
|
||||
return &Router{
|
||||
router: router,
|
||||
swaggerSchema: r.swaggerSchema,
|
||||
context: r.context,
|
||||
jsonDocumentationPath: r.jsonDocumentationPath,
|
||||
yamlDocumentationPath: r.yamlDocumentationPath,
|
||||
pathPrefix: opts.PathPrefix,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
112
main_test.go
112
main_test.go
@@ -17,7 +17,8 @@ import (
|
||||
)
|
||||
|
||||
func TestNewRouter(t *testing.T) {
|
||||
mRouter := apirouter.NewGorillaMuxRouter(mux.NewRouter())
|
||||
muxRouter := mux.NewRouter()
|
||||
mAPIRouter := apirouter.NewGorillaMuxRouter(muxRouter)
|
||||
|
||||
info := &openapi3.Info{
|
||||
Title: "my title",
|
||||
@@ -29,21 +30,21 @@ func TestNewRouter(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("not ok - invalid Openapi option", func(t *testing.T) {
|
||||
r, err := NewRouter(mRouter, Options{})
|
||||
r, err := NewRouter(mAPIRouter, Options{})
|
||||
|
||||
require.Nil(t, r)
|
||||
require.EqualError(t, err, fmt.Sprintf("%s: swagger is required", ErrValidatingSwagger))
|
||||
})
|
||||
|
||||
t.Run("ok - with default context", func(t *testing.T) {
|
||||
r, err := NewRouter(mRouter, Options{
|
||||
r, err := NewRouter(mAPIRouter, Options{
|
||||
Openapi: openapi,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &Router{
|
||||
context: context.Background(),
|
||||
router: mRouter,
|
||||
router: mAPIRouter,
|
||||
swaggerSchema: openapi,
|
||||
jsonDocumentationPath: DefaultJSONDocumentationPath,
|
||||
yamlDocumentationPath: DefaultYAMLDocumentationPath,
|
||||
@@ -53,7 +54,7 @@ func TestNewRouter(t *testing.T) {
|
||||
t.Run("ok - with custom context", func(t *testing.T) {
|
||||
type key struct{}
|
||||
ctx := context.WithValue(context.Background(), key{}, "value")
|
||||
r, err := NewRouter(mRouter, Options{
|
||||
r, err := NewRouter(mAPIRouter, Options{
|
||||
Openapi: openapi,
|
||||
Context: ctx,
|
||||
})
|
||||
@@ -61,7 +62,7 @@ func TestNewRouter(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &Router{
|
||||
context: ctx,
|
||||
router: mRouter,
|
||||
router: mAPIRouter,
|
||||
swaggerSchema: openapi,
|
||||
jsonDocumentationPath: DefaultJSONDocumentationPath,
|
||||
yamlDocumentationPath: DefaultYAMLDocumentationPath,
|
||||
@@ -71,7 +72,7 @@ func TestNewRouter(t *testing.T) {
|
||||
t.Run("ok - with custom docs paths", func(t *testing.T) {
|
||||
type key struct{}
|
||||
ctx := context.WithValue(context.Background(), key{}, "value")
|
||||
r, err := NewRouter(mRouter, Options{
|
||||
r, err := NewRouter(mAPIRouter, Options{
|
||||
Openapi: openapi,
|
||||
Context: ctx,
|
||||
JSONDocumentationPath: "/json/path",
|
||||
@@ -81,7 +82,7 @@ func TestNewRouter(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &Router{
|
||||
context: ctx,
|
||||
router: mRouter,
|
||||
router: mAPIRouter,
|
||||
swaggerSchema: openapi,
|
||||
jsonDocumentationPath: "/json/path",
|
||||
yamlDocumentationPath: "/yaml/path",
|
||||
@@ -91,7 +92,7 @@ func TestNewRouter(t *testing.T) {
|
||||
t.Run("ko - json documentation path does not start with /", func(t *testing.T) {
|
||||
type key struct{}
|
||||
ctx := context.WithValue(context.Background(), key{}, "value")
|
||||
r, err := NewRouter(mRouter, Options{
|
||||
r, err := NewRouter(mAPIRouter, Options{
|
||||
Openapi: openapi,
|
||||
Context: ctx,
|
||||
JSONDocumentationPath: "json/path",
|
||||
@@ -105,7 +106,7 @@ func TestNewRouter(t *testing.T) {
|
||||
t.Run("ko - yaml documentation path does not start with /", func(t *testing.T) {
|
||||
type key struct{}
|
||||
ctx := context.WithValue(context.Background(), key{}, "value")
|
||||
r, err := NewRouter(mRouter, Options{
|
||||
r, err := NewRouter(mAPIRouter, Options{
|
||||
Openapi: openapi,
|
||||
Context: ctx,
|
||||
JSONDocumentationPath: "/json/path",
|
||||
@@ -315,6 +316,97 @@ func TestGenerateAndExposeSwagger(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.YAMLEq(t, string(expected), body, string(body))
|
||||
})
|
||||
|
||||
t.Run("ok - subrouter", func(t *testing.T) {
|
||||
mRouter := mux.NewRouter()
|
||||
|
||||
router, err := NewRouter(apirouter.NewGorillaMuxRouter(mRouter), Options{
|
||||
Openapi: &openapi3.T{
|
||||
Info: &openapi3.Info{
|
||||
Title: "test swagger title",
|
||||
Version: "test swagger version",
|
||||
},
|
||||
},
|
||||
JSONDocumentationPath: "/custom/path",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
router.AddRoute(http.MethodGet, "/foo", func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
}, Definitions{})
|
||||
|
||||
mSubRouter := mRouter.PathPrefix("/prefix").Subrouter()
|
||||
subrouter, err := router.SubRouter(apirouter.NewGorillaMuxRouter(mSubRouter), SubRouterOptions{
|
||||
PathPrefix: "/prefix",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = subrouter.AddRoute(http.MethodGet, "/taz", func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
}, Definitions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("add route with path equal to prefix path", func(t *testing.T) {
|
||||
_, err = subrouter.AddRoute(http.MethodGet, "", func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
}, Definitions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
err = router.GenerateAndExposeSwagger()
|
||||
require.NoError(t, err)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/custom/path", nil)
|
||||
mRouter.ServeHTTP(w, req)
|
||||
|
||||
require.Equal(t, http.StatusOK, w.Result().StatusCode)
|
||||
require.True(t, strings.Contains(w.Result().Header.Get("content-type"), "application/json"))
|
||||
|
||||
body := readBody(t, w.Result().Body)
|
||||
actual, err := ioutil.ReadFile("testdata/subrouter.json")
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, string(actual), body)
|
||||
})
|
||||
|
||||
t.Run("ok - new router with path prefix", func(t *testing.T) {
|
||||
mRouter := mux.NewRouter()
|
||||
|
||||
router, err := NewRouter(apirouter.NewGorillaMuxRouter(mRouter), Options{
|
||||
Openapi: &openapi3.T{
|
||||
Info: &openapi3.Info{
|
||||
Title: "test swagger title",
|
||||
Version: "test swagger version",
|
||||
},
|
||||
},
|
||||
JSONDocumentationPath: "/custom/path",
|
||||
PathPrefix: "/prefix",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
router.AddRoute(http.MethodGet, "/foo", func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
}, Definitions{})
|
||||
|
||||
err = router.GenerateAndExposeSwagger()
|
||||
require.NoError(t, err)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/custom/path", nil)
|
||||
mRouter.ServeHTTP(w, req)
|
||||
|
||||
require.Equal(t, http.StatusOK, w.Result().StatusCode)
|
||||
require.True(t, strings.Contains(w.Result().Header.Get("content-type"), "application/json"))
|
||||
|
||||
body := readBody(t, w.Result().Body)
|
||||
actual, err := ioutil.ReadFile("testdata/router_with_prefix.json")
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, string(actual), body)
|
||||
})
|
||||
}
|
||||
|
||||
func readBody(t *testing.T, requestBody io.ReadCloser) string {
|
||||
|
||||
8
route.go
8
route.go
@@ -3,6 +3,7 @@ package swagger
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
"github.com/alecthomas/jsonschema"
|
||||
@@ -23,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
|
||||
func (r Router) AddRawRoute(method string, path string, handler apirouter.HandlerFunc, operation Operation) (interface{}, error) {
|
||||
func (r Router) AddRawRoute(method string, routePath string, handler apirouter.HandlerFunc, operation Operation) (interface{}, error) {
|
||||
op := operation.Operation
|
||||
if op != nil {
|
||||
err := operation.Validate(r.context)
|
||||
@@ -36,10 +37,11 @@ func (r Router) AddRawRoute(method string, path string, handler apirouter.Handle
|
||||
op.Responses = openapi3.NewResponses()
|
||||
}
|
||||
}
|
||||
r.swaggerSchema.AddOperation(path, method, op)
|
||||
pathWithPrefix := path.Join(r.pathPrefix, routePath)
|
||||
r.swaggerSchema.AddOperation(pathWithPrefix, method, op)
|
||||
|
||||
// Handle, when content-type is json, the request/response marshalling? Maybe with a specific option.
|
||||
return r.router.AddRoute(path, method, handler), nil
|
||||
return r.router.AddRoute(pathWithPrefix, method, handler), nil
|
||||
}
|
||||
|
||||
// Content is the type of a content.
|
||||
|
||||
19
testdata/router_with_prefix.json
vendored
Normal file
19
testdata/router_with_prefix.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"components": {},
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/prefix/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
testdata/subrouter.json
vendored
Normal file
37
testdata/subrouter.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"components": {},
|
||||
"info": {
|
||||
"title": "test swagger title",
|
||||
"version": "test swagger version"
|
||||
},
|
||||
"openapi": "3.0.0",
|
||||
"paths": {
|
||||
"/foo": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/prefix/taz": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/prefix": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user