From 7b5e1d762cc653030789f19d69de945c68ca4c3c Mon Sep 17 00:00:00 2001 From: ElvinChan Date: Sun, 2 Sep 2018 10:22:18 +0800 Subject: [PATCH] Add interface ApiRouter --- README.md | 43 ++++++++++++++++++++++++++- wrapper.go | 44 +++++++++++++++++++++------- wrapper_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 wrapper_test.go diff --git a/README.md b/README.md index edebdbf..b792c13 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,46 @@ Swagger UI generator for Echo framework [![Go Report Card](https://goreportcard.com/badge/github.com/elvinchan/echoswagger)](https://goreportcard.com/report/github.com/elvinchan/echoswagger) - [![Build Status](https://travis-ci.org/elvinchan/echoswagger.svg?branch=master)](https://travis-ci.org/elvinchan/echoswagger) +[![codecov](https://codecov.io/gh/elvinchan/echoswagger/branch/master/graph/badge.svg)](https://codecov.io/gh/elvinchan/echoswagger) + +## Feature +- No SwaggerUI html/css dependency +- Highly integrated with echo, low intrusive design +- Take advantage of the strong typing language to make it easy to use +- Recycle garbage in time, low memory usage + +## Example +```go +package main + +import ( + "net/http" + + "github.com/elvinchan/echoswagger" + "github.com/labstack/echo" +) + +func main() { + // ApiRoot with Echo instance + e := echoswagger.New(echo.New(), "/v2", "doc/", nil) + + // Routes with parameters & responses + e.POST("/", createUser). + AddParamBody(User{}, "body", "User input struct", true). + AddResponse(http.StatusCreated, "successful", nil, nil) + + // Start server + e.Echo().Logger.Fatal(e.Echo().Start(":1323")) +} + +type User struct { + Name string +} + +// Handler +func createUser(c echo.Context) error { + return c.JSON(http.StatusCreated, nil) +} + +``` diff --git a/wrapper.go b/wrapper.go index f56903f..c593b17 100644 --- a/wrapper.go +++ b/wrapper.go @@ -20,7 +20,23 @@ Notice: 4.只支持基本类型的Map Key */ +type ApiRouter interface { + // GET overrides `Echo#GET()` for sub-routes within the ApiGroup. + GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api + + // POST overrides `Echo#POST()` for sub-routes within the ApiGroup. + POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api + + // PUT overrides `Echo#PUT()` for sub-routes within the ApiGroup. + PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api + + // DELETE overrides `Echo#DELETE()` for sub-routes within the ApiGroup. + DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api +} + type ApiRoot interface { + ApiRouter + // ApiGroup creates ApiGroup. Use this instead of Echo#ApiGroup. Group(name, prefix string, m ...echo.MiddlewareFunc) ApiGroup @@ -53,17 +69,7 @@ type ApiRoot interface { } type ApiGroup interface { - // GET overrides `Echo#GET()` for sub-routes within the ApiGroup. - GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api - - // POST overrides `Echo#POST()` for sub-routes within the ApiGroup. - POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api - - // PUT overrides `Echo#PUT()` for sub-routes within the ApiGroup. - PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api - - // DELETE overrides `Echo#DELETE()` for sub-routes within the ApiGroup. - DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api + ApiRouter // SetDescription sets description for ApiGroup. SetDescription(desc string) ApiGroup @@ -220,6 +226,22 @@ func New(e *echo.Echo, basePath, docPath string, i *Info) ApiRoot { return r } +func (r *Root) GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api { + return r.appendRoute(echo.GET, r.echo.GET(path, h, m...)) +} + +func (r *Root) POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api { + return r.appendRoute(echo.POST, r.echo.POST(path, h, m...)) +} + +func (r *Root) PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api { + return r.appendRoute(echo.PUT, r.echo.PUT(path, h, m...)) +} + +func (r *Root) DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) Api { + return r.appendRoute(echo.DELETE, r.echo.DELETE(path, h, m...)) +} + func (r *Root) Group(name, prefix string, m ...echo.MiddlewareFunc) ApiGroup { if name == "" { panic("echowagger: invalid name of ApiGroup") diff --git a/wrapper_test.go b/wrapper_test.go new file mode 100644 index 0000000..bce3ada --- /dev/null +++ b/wrapper_test.go @@ -0,0 +1,77 @@ +package echoswagger + +import ( + "testing" + + "github.com/labstack/echo" + "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + tests := []struct { + echo *echo.Echo + basePath string + docPath string + info *Info + expectPaths []string + panic bool + name string + }{ + { + echo: echo.New(), + basePath: "/", + docPath: "doc/", + info: nil, + expectPaths: []string{"/doc/", "/doc/swagger.json"}, + panic: false, + name: "Normal", + }, + { + echo: echo.New(), + basePath: "/", + docPath: "doc", + info: &Info{ + Title: "Test project", + Contact: &Contact{ + URL: "https://github.com/elvinchan/echoswagger", + }, + }, + expectPaths: []string{"/doc", "/doc/swagger.json"}, + panic: false, + name: "Path slash suffix", + }, + { + echo: nil, + panic: true, + name: "Panic", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.panic { + assert.Panics(t, func() { + New(tt.echo, tt.basePath, tt.docPath, tt.info) + }) + } else { + apiRoot := New(tt.echo, tt.basePath, tt.docPath, tt.info) + assert.NotNil(t, apiRoot.(*Root)) + + root := apiRoot.(*Root) + assert.NotNil(t, root.spec) + + assert.Equal(t, root.spec.BasePath, tt.basePath) + if tt.info == nil { + assert.Equal(t, root.spec.Info.Title, "Project APIs") + } else { + assert.Equal(t, root.spec.Info, tt.info) + } + + assert.NotNil(t, root.echo) + assert.Len(t, root.echo.Routes(), 2) + res := root.echo.Routes() + paths := []string{res[0].Path, res[1].Path} + assert.ElementsMatch(t, paths, tt.expectPaths) + } + }) + } +}