Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
a364495b1a | |||
05293f86ba | |||
39f5b3dbbf | |||
c7432de845 | |||
f2262c67cf | |||
fb1c53169c | |||
|
2fa7b58c03 | ||
|
713d93196b | ||
|
e4b714794f | ||
|
d715040d11 | ||
|
795eb4e894 | ||
|
526c519e76 | ||
|
818f3e3ce0 | ||
|
cb60195b27 |
9
.gitignore
vendored
9
.gitignore
vendored
@ -12,4 +12,11 @@
|
||||
*.out
|
||||
|
||||
.DS_Store
|
||||
tmp
|
||||
tmp
|
||||
*.bak
|
||||
vendor/
|
||||
.cache/
|
||||
.idea/
|
||||
bin/*.macos
|
||||
bin/*.linux
|
||||
bin/*.exe
|
||||
|
@ -1,10 +1,11 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
|
214
LICENSE
214
LICENSE
@ -1,21 +1,201 @@
|
||||
MIT License
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2018 陈文强
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
1. Definitions.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
40
README.md
40
README.md
@ -1,11 +1,20 @@
|
||||
English | [简体中文](./README_zh-CN.md)
|
||||
English version
|
||||
|
||||
# Echoswagger
|
||||
Swagger UI generator for Echo framework
|
||||
Swagger UI generator for Echo framework, v4
|
||||
|
||||
[](https://goreportcard.com/report/github.com/pangpanglabs/echoswagger)
|
||||
[](https://travis-ci.org/pangpanglabs/echoswagger)
|
||||
[](https://codecov.io/gh/pangpanglabs/echoswagger)
|
||||
[](https://goreportcard.com/report/git.webz.asia/echo-go/echoswagger)
|
||||
[](https://travis-ci.org/echo-go/echoswagger)
|
||||
[](https://codecov.io/gh/echo-go/echoswagger)
|
||||
|
||||
## Differences
|
||||
This is fork of [pangpanglabs/echoswagger](https://github.com/pangpanglabs/echoswagger)
|
||||
|
||||
With several differences:
|
||||
* Switched to [Echo framework, v4](https://github.com/labstack/echo/tree/v4.1.11)
|
||||
* Modular dependencies support
|
||||
* Switched to [Apache 2.0](https://git.webz.asia/echo-go/echoswagger/blob/master/LICENSE) license
|
||||
* Builder docker script for example code
|
||||
|
||||
## Feature
|
||||
- No SwaggerUI HTML/CSS dependency
|
||||
@ -15,7 +24,7 @@ Swagger UI generator for Echo framework
|
||||
|
||||
## Installation
|
||||
```
|
||||
go get github.com/pangpanglabs/echoswagger
|
||||
go get git.webz.asia/echo-go/echoswagger
|
||||
```
|
||||
|
||||
## Example
|
||||
@ -25,13 +34,20 @@ package main
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.Logger())
|
||||
|
||||
// ApiRoot with Echo instance
|
||||
r := echoswagger.New(echo.New(), "", "doc/", nil)
|
||||
r := echoswagger.New(e, "/doc", nil)
|
||||
|
||||
// Routes with parameters & responses
|
||||
r.POST("/", createUser).
|
||||
@ -56,10 +72,8 @@ func createUser(c echo.Context) error {
|
||||
## Usage
|
||||
#### Create a `ApiRoot` with `New()`, which is a wrapper of `echo.New()`
|
||||
```
|
||||
r := echoswagger.New(echo.New(), "/v1", "doc/", nil)
|
||||
r := echoswagger.New(echo.New(), "/doc", nil)
|
||||
```
|
||||
> Note: The parameter `basePath` is generally used when the access root path is not the root directory of the website after application is deployed. For example, the URL of an API in the program running locally is: `http://localhost:1323/users`, the actual URL after deployed to server is: `https://www.xxx.com/legacy-api/users`, then, when running locally, `basePath` should be `/`, when running on server, `basePath` should be `/legacy-api`.
|
||||
|
||||
You can use the result `ApiRoot` instance to:
|
||||
- Setup Security definitions, request/response Content-Types, UI options, Scheme, etc.
|
||||
```
|
||||
@ -228,4 +242,4 @@ default | * | Default value, which type is same as the field's type.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/pangpanglabs/echoswagger/blob/master/LICENSE)
|
||||
[Apache 2.0](https://git.webz.asia/echo-go/echoswagger/blob/master/LICENSE)
|
||||
|
231
README_zh-CN.md
231
README_zh-CN.md
@ -1,231 +0,0 @@
|
||||
[English](./README.md) | 简体中文
|
||||
|
||||
# Echoswagger
|
||||
[Echo](https://github.com/labstack/echo) 框架的 [Swagger UI](https://github.com/swagger-api/swagger-ui) 生成器
|
||||
|
||||
[](https://goreportcard.com/report/github.com/pangpanglabs/echoswagger)
|
||||
[](https://travis-ci.org/pangpanglabs/echoswagger)
|
||||
[](https://codecov.io/gh/pangpanglabs/echoswagger)
|
||||
|
||||
## 特性
|
||||
- 不依赖任何SwaggerUI的HTML/CSS文件
|
||||
- 与Echo高度整合,低侵入式设计
|
||||
- 利用强类型语言和链式编程的优势,简单易用
|
||||
- 及时的垃圾回收,低内存占用
|
||||
|
||||
## 安装
|
||||
```
|
||||
go get github.com/pangpanglabs/echoswagger
|
||||
```
|
||||
|
||||
## 示例
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// ApiRoot with Echo instance
|
||||
r := echoswagger.New(echo.New(), "", "doc/", nil)
|
||||
|
||||
// Routes with parameters & responses
|
||||
r.POST("/", createUser).
|
||||
AddParamBody(User{}, "body", "User input struct", true).
|
||||
AddResponse(http.StatusCreated, "successful", nil, nil)
|
||||
|
||||
// Start server
|
||||
r.Echo().Logger.Fatal(r.Echo().Start(":1323"))
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Handler
|
||||
func createUser(c echo.Context) error {
|
||||
return c.JSON(http.StatusCreated, nil)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 用法
|
||||
#### 用`New()`创建`ApiRoot`,此方法是对`echo.New()`方法的封装
|
||||
```
|
||||
r := echoswagger.New(echo.New(), "/v1", "doc/", nil)
|
||||
```
|
||||
> 注意:参数`basePath`一般用于程序部署后访问路径并非网站根目录时的情况,比如程序运行在本地的某个API的URL为:`http://localhost:1323/users`,部署至服务器后的实际URL为:`https://www.xxx.com/legacy-api/users`,则本地运行时,`basePath`应该传入`/`, 部署至服务器时,`basePath`应该传入`/legacy-api`。
|
||||
|
||||
你可以用这个`ApiRoot`来:
|
||||
- 设置Security定义, 请求/响应Content-Type,UI选项,Scheme等。
|
||||
```
|
||||
r.AddSecurityAPIKey("JWT", "JWT Token", echoswagger.SecurityInHeader).
|
||||
SetRequestContentType("application/x-www-form-urlencoded", "multipart/form-data").
|
||||
SetUI(UISetting{HideTop: true}).
|
||||
SetScheme("https", "http")
|
||||
```
|
||||
- 获取`echo.Echo`实例。
|
||||
```
|
||||
r.Echo()
|
||||
```
|
||||
- 在默认组中注册一个GET、POST、PUT、DELETE、OPTIONS、HEAD或PATCH路由,这些是对Echo的注册路由方法的封装。
|
||||
此方法返回一个`Api`实例。
|
||||
```
|
||||
r.GET("/:id", handler)
|
||||
```
|
||||
- 以及: ↓
|
||||
|
||||
#### 用`Group()`创建`ApiGroup`,此方法是对`echo.Group()`方法的封装
|
||||
```
|
||||
g := r.Group("Users", "/users")
|
||||
```
|
||||
你可以用这个`ApiGroup`来:
|
||||
- 设置描述,等。
|
||||
```
|
||||
g.SetDescription("The desc of group")
|
||||
```
|
||||
- 为此组中的所有路由设置Security。
|
||||
```
|
||||
g.SetSecurity("JWT")
|
||||
```
|
||||
- 获取`echo.Group`实例。
|
||||
```
|
||||
g.EchoGroup()
|
||||
```
|
||||
- 以及: ↓
|
||||
|
||||
#### 在`ApiGroup`中注册一个新的路由
|
||||
Echoswagger支持GET、POST、PUT、DELETE、OPTIONS、HEAD或PATCH方法,这些是对Echo的注册路由方法的封装。
|
||||
```
|
||||
a := g.GET("/:id", handler)
|
||||
```
|
||||
你可以使用此`Api`实例来:
|
||||
- 使用以下方法添加参数:
|
||||
```
|
||||
AddParamPath(p interface{}, name, desc string)
|
||||
|
||||
AddParamPathNested(p interface{})
|
||||
|
||||
AddParamQuery(p interface{}, name, desc string, required bool)
|
||||
|
||||
AddParamQueryNested(p interface{})
|
||||
|
||||
AddParamForm(p interface{}, name, desc string, required bool)
|
||||
|
||||
AddParamFormNested(p interface{})
|
||||
|
||||
AddParamHeader(p interface{}, name, desc string, required bool)
|
||||
|
||||
AddParamHeaderNested(p interface{})
|
||||
|
||||
AddParamBody(p interface{}, name, desc string, required bool)
|
||||
|
||||
AddParamFile(name, desc string, required bool)
|
||||
```
|
||||
|
||||
后缀带有`Nested`的方法把参数`p`的字段看做多个参数,所以它必须是结构体类型的。
|
||||
|
||||
例:
|
||||
```
|
||||
type SearchInput struct {
|
||||
Q string `query:"q" swagger:"desc(Keywords),required"`
|
||||
SkipCount int `query:"skipCount"`
|
||||
}
|
||||
a.AddParamQueryNested(SearchInput{})
|
||||
```
|
||||
等价于:
|
||||
```
|
||||
a.AddParamQuery("", "q", "Keywords", true).
|
||||
AddParamQuery(0, "skipCount", "", false)
|
||||
```
|
||||
- 添加响应。
|
||||
```
|
||||
a.AddResponse(http.StatusOK, "response desc", body{}, nil)
|
||||
```
|
||||
- 设置Security,请求/响应的Content-Type,概要,描述,等。
|
||||
```
|
||||
a.SetSecurity("JWT").
|
||||
SetResponseContentType("application/xml").
|
||||
SetSummary("The summary of API").
|
||||
SetDescription("The desc of API")
|
||||
```
|
||||
- 获取`echo.Route`实例。
|
||||
```
|
||||
a.Route()
|
||||
```
|
||||
|
||||
#### 使用swagger标签,你可以在`AddParam...`方法中设置更多信息
|
||||
例:
|
||||
```
|
||||
type User struct {
|
||||
Age int `swagger:"min(0),max(99)"`
|
||||
Gender string `swagger:"enum(male|female|other),required"`
|
||||
Money []float64 `swagger:"default(0),readOnly"`
|
||||
}
|
||||
a.AddParamBody(&User{}, "Body", "", true)
|
||||
```
|
||||
此定义等价于:
|
||||
```
|
||||
{
|
||||
"definitions": {
|
||||
"User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Age": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"minimum": 0,
|
||||
"maximum": 99
|
||||
},
|
||||
"Gender": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"male",
|
||||
"female",
|
||||
"other"
|
||||
],
|
||||
"format": "string"
|
||||
},
|
||||
"Money": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number",
|
||||
"default": 0,
|
||||
"format": "double"
|
||||
},
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Gender"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**支持的`swagger`标签:**
|
||||
|
||||
Tag | Type | Description
|
||||
---|:---:|---
|
||||
desc | `string` | 描述。
|
||||
maximum | `number` | -
|
||||
minimum | `number` | -
|
||||
maxLength | `integer` | -
|
||||
minLength | `integer` | -
|
||||
allowEmpty | `boolean` | 设置传递空值参数的功能。 这仅对`query`或`formData`参数有效,并允许你发送仅具有名称或空值的参数。默认值为“false”。
|
||||
required | `boolean` | 确定此参数是否必需。如果参数是`in`“path”,则此属性默认为“true”。否则,可以设置此属性,其默认值为“false”。
|
||||
readOnly | `boolean` | 仅与Schema`"properties"`定义相关。将属性声明为“只读”。这意味着它可以作为响应的一部分发送,但绝不能作为请求的一部分发送。标记为“readOnly”的属性为“true”,不应位于已定义模式的“required”列表中。默认值为“false”。
|
||||
enum | [*] | 枚举值,多个值应以“\|”分隔。
|
||||
default | * | 默认值,该类型与字段的类型相同。
|
||||
|
||||
## 参考
|
||||
[OpenAPI Specification 2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/pangpanglabs/echoswagger/blob/master/LICENSE)
|
47
assets.go
47
assets.go
@ -1,7 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
// CDN refer to https://www.jsdelivr.com/package/npm/swagger-ui-dist
|
||||
const DefaultCDN = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.19.0"
|
||||
const DefaultCDN = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@3.22.1"
|
||||
|
||||
const SwaggerUIContent = `{{define "swagger"}}
|
||||
<!DOCTYPE html>
|
||||
@ -47,10 +68,27 @@ const SwaggerUIContent = `{{define "swagger"}}
|
||||
<script src="{{.cdn}}/swagger-ui-standalone-preset.js" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
|
||||
// Build a system
|
||||
var specPath = "{{.specName}}"
|
||||
if (!window.location.pathname.endsWith("/")) {
|
||||
specPath = "/" + specPath
|
||||
}
|
||||
var specStr = "{{.spec}}"
|
||||
var spec = specStr ? JSON.parse(specStr) : undefined
|
||||
if (spec) {
|
||||
spec.host = window.location.host
|
||||
var docPath = "{{.docPath}}"
|
||||
var basePath = window.location.pathname
|
||||
if (!docPath.endsWith("/")) { docPath += "/" }
|
||||
if (!basePath.endsWith("/")) { basePath += "/" }
|
||||
if (basePath.endsWith(docPath)) {
|
||||
basePath = basePath.slice(0, -docPath.length)
|
||||
}
|
||||
spec.basePath = basePath
|
||||
}
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: this.window.location.origin+{{.path}},
|
||||
url: window.location.origin+window.location.pathname+specPath,
|
||||
spec: spec,
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
@ -62,6 +100,7 @@ const SwaggerUIContent = `{{define "swagger"}}
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
})
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui
|
||||
}
|
||||
|
0
bin/.gitkeep
Normal file
0
bin/.gitkeep
Normal file
13
build/Dockerfile
Normal file
13
build/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM golang
|
||||
|
||||
LABEL maintainer="alex@webz.asia"
|
||||
|
||||
RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
||||
|
||||
ENV GOPATH=/go
|
||||
|
||||
VOLUME /go
|
||||
|
||||
WORKDIR /go
|
||||
|
||||
CMD ["go", "version"]
|
54
build/build.sh
Executable file
54
build/build.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# @author Alex aka mailoman <alex@webz.asia>
|
||||
# @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
# @since 18.12.2019
|
||||
|
||||
path=$(pwd)
|
||||
dir="${path%/*}"
|
||||
path=${dir}
|
||||
repo="${dir##*/}"
|
||||
dir="${dir%/*}"
|
||||
username=${dir##*/}
|
||||
dir="${dir%/*}"
|
||||
domain=${dir##*/}
|
||||
image="go2dep"
|
||||
image_exists=$(docker images|grep ${image})
|
||||
volume_cache="-v ${path}/.cache:/go/pkg"
|
||||
|
||||
if [[ -z ${image_exists} ]];then
|
||||
echo "building image ${image}"
|
||||
docker build -t ${image} .
|
||||
fi
|
||||
|
||||
if [[ ! -d ${path}/vendor ]];then
|
||||
echo "dep init"
|
||||
docker run --rm ${volume_cache} -v ${path}:/go/src/$domain/$username/$repo -w="/go/src/$domain/$username/$repo" ${image} dep init
|
||||
fi
|
||||
|
||||
echo "Building $domain/$username/$repo/examples/main.go"
|
||||
|
||||
#buildVersion=$(git tag|tail -n1)
|
||||
#buildHash=$(git log -1 --pretty=format:"%h")
|
||||
#buildTime=$(date)
|
||||
#buildFlags="-X '$domain/$username/$repo/version.BuildVersion=${buildVersion}' -X '$domain/$username/$repo/version.BuildHash=${buildHash}' -X '$domain/$username/$repo/version.BuildTime=${buildTime}'"
|
||||
buildFlags=""
|
||||
|
||||
echo " build flags: ${buildFlags}"
|
||||
|
||||
docker run --rm ${volume_cache} -v ${path}:/go/src/$domain/$username/$repo -v ${path}/bin:/go/bin -w="/go/src/$domain/$username/$repo" -e GOOS=linux -e GOARCH=amd64 -e CGO_ENABLED=0 ${image} go build -ldflags="${buildFlags}" -o /go/bin/example-main-x64.linux ./examples/
|
||||
docker run --rm ${volume_cache} -v ${path}:/go/src/$domain/$username/$repo -v ${path}/bin:/go/bin -w="/go/src/$domain/$username/$repo" -e GOOS=darwin -e GOARCH=amd64 -e CGO_ENABLED=0 ${image} go build -ldflags="${buildFlags}" -o /go/bin/example-main-x64.macos ./examples/
|
||||
docker run --rm ${volume_cache} -v ${path}:/go/src/$domain/$username/$repo -v ${path}/bin:/go/bin -w="/go/src/$domain/$username/$repo" -e GOOS=windows -e GOARCH=amd64 -e CGO_ENABLED=0 ${image} go build -ldflags="${buildFlags}" -o /go/bin/example-main-x64.exe ./examples/
|
21
converter.go
21
converter.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
@ -1,10 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
type PetController struct{}
|
||||
|
@ -1,11 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
type StoreController struct{}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -5,8 +26,9 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
type UserController struct{}
|
||||
|
@ -1,8 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -13,7 +36,10 @@ func main() {
|
||||
func initServer() echoswagger.ApiRoot {
|
||||
e := echo.New()
|
||||
|
||||
se := echoswagger.New(e, "", "doc/", &echoswagger.Info{
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.Logger())
|
||||
|
||||
se := echoswagger.New(e, "doc/", &echoswagger.Info{
|
||||
Title: "Swagger Petstore",
|
||||
Description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
|
||||
Version: "1.0.0",
|
||||
@ -36,7 +62,7 @@ func initServer() echoswagger.ApiRoot {
|
||||
|
||||
se.SetExternalDocs("Find out more about Swagger", "http://swagger.io").
|
||||
SetResponseContentType("application/xml", "application/json").
|
||||
SetUI(echoswagger.UISetting{HideTop: true}).
|
||||
SetUI(echoswagger.UISetting{DetachSpec: true, HideTop: true}).
|
||||
SetScheme("https", "http")
|
||||
|
||||
PetController{}.Init(se.Group("pet", "/pet"))
|
||||
|
@ -1,14 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/pangpanglabs/echoswagger"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"git.webz.asia/echo-go/echoswagger"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
@ -18,8 +40,9 @@ func TestMain(t *testing.T) {
|
||||
c := e.Echo().NewContext(req, rec)
|
||||
b, err := ioutil.ReadFile("./swagger.json")
|
||||
assert.Nil(t, err)
|
||||
if assert.NoError(t, e.(*echoswagger.Root).Spec(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.JSONEq(t, string(b), rec.Body.String())
|
||||
}
|
||||
s, err := e.(*echoswagger.Root).GetSpec(c, "/doc")
|
||||
assert.Nil(t, err)
|
||||
rs, err := json.Marshal(s)
|
||||
assert.Nil(t, err)
|
||||
assert.JSONEq(t, string(b), string(rs))
|
||||
}
|
||||
|
@ -13,8 +13,6 @@
|
||||
},
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"host": "example.com",
|
||||
"basePath": "/",
|
||||
"schemes": [
|
||||
"https",
|
||||
"http"
|
||||
|
21
generator.go
21
generator.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
9
go.mod
Normal file
9
go.mod
Normal file
@ -0,0 +1,9 @@
|
||||
module git.webz.asia/echo-go/echoswagger/v2
|
||||
|
||||
require (
|
||||
github.com/labstack/echo v3.3.10+incompatible // indirect
|
||||
github.com/labstack/echo/v4 v4.1.11
|
||||
github.com/stretchr/testify v1.4.0
|
||||
)
|
||||
|
||||
go 1.13
|
39
go.sum
Normal file
39
go.sum
Normal file
@ -0,0 +1,39 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
|
||||
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
|
||||
github.com/labstack/echo/v4 v4.1.11 h1:z0BZoArY4FqdpUEl+wlHp4hnr/oSR6MTmQmv8OHSoww=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
58
internal.go
58
internal.go
@ -1,12 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type ParamInType string
|
||||
@ -20,8 +42,9 @@ const (
|
||||
)
|
||||
|
||||
type UISetting struct {
|
||||
HideTop bool
|
||||
CDN string
|
||||
DetachSpec bool
|
||||
HideTop bool
|
||||
CDN string
|
||||
}
|
||||
|
||||
type RawDefineDic map[string]RawDefine
|
||||
@ -31,7 +54,7 @@ type RawDefine struct {
|
||||
Schema *JSONSchema
|
||||
}
|
||||
|
||||
func (r *Root) docHandler(realSpecPath string) echo.HandlerFunc {
|
||||
func (r *Root) docHandler(docPath string) echo.HandlerFunc {
|
||||
t, err := template.New("swagger").Parse(SwaggerUIContent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -42,12 +65,27 @@ func (r *Root) docHandler(realSpecPath string) echo.HandlerFunc {
|
||||
cdn = DefaultCDN
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
t.Execute(buf, map[string]interface{}{
|
||||
"title": r.spec.Info.Title,
|
||||
"hideTop": r.ui.HideTop,
|
||||
"path": realSpecPath,
|
||||
"cdn": cdn,
|
||||
})
|
||||
params := map[string]interface{}{
|
||||
"title": r.spec.Info.Title,
|
||||
"cdn": cdn,
|
||||
"specName": SpecName,
|
||||
}
|
||||
if !r.ui.DetachSpec {
|
||||
spec, err := r.GetSpec(c, docPath)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
b, err := json.Marshal(spec)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
params["spec"] = string(b)
|
||||
params["docPath"] = docPath
|
||||
params["hideTop"] = true
|
||||
} else {
|
||||
params["hideTop"] = r.ui.HideTop
|
||||
}
|
||||
t.Execute(buf, params)
|
||||
return c.HTMLBlob(http.StatusOK, buf.Bytes())
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
21
models.go
21
models.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
type (
|
||||
|
21
security.go
21
security.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import "errors"
|
||||
|
@ -1,15 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSecurity(t *testing.T) {
|
||||
r := New(echo.New(), "/", "doc/", nil)
|
||||
r := New(echo.New(), "doc/", nil)
|
||||
scope := map[string]string{
|
||||
"read:users": "read users",
|
||||
"write:users": "modify users",
|
||||
@ -194,7 +215,7 @@ func TestSecurity(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSecurityRepeat(t *testing.T) {
|
||||
r := New(echo.New(), "/", "doc/", nil)
|
||||
r := New(echo.New(), "doc/", nil)
|
||||
scope := map[string]string{
|
||||
"read:users": "read users",
|
||||
"write:users": "modify users",
|
||||
|
55
spec.go
55
spec.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
@ -6,28 +27,44 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
DefPrefix = "#/definitions/"
|
||||
SwaggerVersion = "2.0"
|
||||
SpecName = "swagger.json"
|
||||
)
|
||||
|
||||
func (r *Root) Spec(c echo.Context) error {
|
||||
func (r *Root) specHandler(docPath string) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
spec, err := r.GetSpec(c, docPath)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
var basePath string
|
||||
if uri, err := url.ParseRequestURI(c.Request().Referer()); err == nil {
|
||||
basePath = trimSuffixSlash(uri.Path, docPath)
|
||||
spec.Host = uri.Host
|
||||
} else {
|
||||
basePath = trimSuffixSlash(c.Request().URL.Path, connectPath(docPath, SpecName))
|
||||
spec.Host = c.Request().Host
|
||||
}
|
||||
spec.BasePath = basePath
|
||||
return c.JSON(http.StatusOK, spec)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate swagger spec data, without host & basePath info
|
||||
func (r *Root) GetSpec(c echo.Context, docPath string) (Swagger, error) {
|
||||
r.once.Do(func() {
|
||||
r.err = r.genSpec(c)
|
||||
r.cleanUp()
|
||||
})
|
||||
if r.err != nil {
|
||||
return c.String(http.StatusInternalServerError, r.err.Error())
|
||||
return Swagger{}, r.err
|
||||
}
|
||||
if uri, err := url.ParseRequestURI(c.Request().Referer()); err == nil {
|
||||
r.spec.Host = uri.Host
|
||||
} else {
|
||||
r.spec.Host = c.Request().Host
|
||||
}
|
||||
return c.JSON(http.StatusOK, r.spec)
|
||||
return *r.spec, nil
|
||||
}
|
||||
|
||||
func (r *Root) genSpec(c echo.Context) error {
|
||||
|
167
spec_test.go
167
spec_test.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
@ -7,7 +28,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -20,13 +41,42 @@ func TestSpec(t *testing.T) {
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","basePath":"/","paths":{}}`
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","paths":{}}`
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc/")(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.JSONEq(t, j, rec.Body.String())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BasicGenerater", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"paths":{}}`
|
||||
s, err := r.(*Root).GetSpec(c, "/doc/")
|
||||
assert.Nil(t, err)
|
||||
rs, err := json.Marshal(s)
|
||||
assert.Nil(t, err)
|
||||
assert.JSONEq(t, j, string(rs))
|
||||
})
|
||||
|
||||
t.Run("BasicIntegrated", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
r.SetUI(UISetting{DetachSpec: false})
|
||||
e := r.(*Root).echo
|
||||
req := httptest.NewRequest(echo.GET, "/doc", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"paths":{}}`
|
||||
s, err := r.(*Root).GetSpec(c, "/doc/")
|
||||
assert.Nil(t, err)
|
||||
rs, err := json.Marshal(s)
|
||||
assert.Nil(t, err)
|
||||
assert.JSONEq(t, j, string(rs))
|
||||
})
|
||||
|
||||
t.Run("Methods", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
var h echo.HandlerFunc
|
||||
@ -41,7 +91,7 @@ func TestSpec(t *testing.T) {
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
s := r.(*Root).spec
|
||||
assert.Len(t, s.Paths, 1)
|
||||
@ -55,32 +105,6 @@ func TestSpec(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ErrorGroupSecurity", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
var h echo.HandlerFunc
|
||||
r.Group("G", "/g").SetSecurity("JWT").GET("/", h)
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ErrorApiSecurity", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
var h echo.HandlerFunc
|
||||
r.GET("/", h).SetSecurity("JWT")
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("CleanUp", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
@ -95,8 +119,8 @@ func TestSpec(t *testing.T) {
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","basePath":"/","paths":{"/ping":{"get":{"responses":{"default":{"description":"successful operation"}}}},"/users/{id}":{"delete":{"tags":["Users"],"responses":{"default":{"description":"successful operation"}}}}},"tags":[{"name":"Users"}]}`
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
j := `{"swagger":"2.0","info":{"title":"Project APIs","version":""},"host":"example.com","paths":{"/ping":{"get":{"responses":{"default":{"description":"successful operation"}}}},"/users/{id}":{"delete":{"tags":["Users"],"responses":{"default":{"description":"successful operation"}}}}},"tags":[{"name":"Users"}]}`
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.JSONEq(t, j, rec.Body.String())
|
||||
}
|
||||
@ -108,29 +132,72 @@ func TestSpec(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestRefererHost(t *testing.T) {
|
||||
func TestReferer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, referer, host string
|
||||
name, referer, host, docPath, basePath string
|
||||
}{
|
||||
{
|
||||
referer: "http://localhost:1323/doc",
|
||||
host: "localhost:1323",
|
||||
name: "A",
|
||||
referer: "http://localhost:1323/doc",
|
||||
host: "localhost:1323",
|
||||
docPath: "/doc",
|
||||
name: "A",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "1/doc",
|
||||
host: "127.0.0.1",
|
||||
name: "B",
|
||||
referer: "http://localhost:1323/doc",
|
||||
host: "localhost:1323",
|
||||
docPath: "/doc/",
|
||||
name: "B",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "http://user:pass@github.com",
|
||||
host: "github.com",
|
||||
name: "C",
|
||||
referer: "http://localhost:1323/doc/",
|
||||
host: "localhost:1323",
|
||||
docPath: "/doc",
|
||||
name: "C",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "https://www.github.com?q=1",
|
||||
host: "www.github.com",
|
||||
name: "D",
|
||||
referer: "http://localhost:1323/api/v1/doc",
|
||||
host: "localhost:1323",
|
||||
docPath: "/doc",
|
||||
name: "D",
|
||||
basePath: "/api/v1",
|
||||
},
|
||||
{
|
||||
referer: "1/doc",
|
||||
host: "127.0.0.1",
|
||||
docPath: "/doc",
|
||||
name: "E",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "http://user:pass@github.com",
|
||||
host: "github.com",
|
||||
docPath: "/",
|
||||
name: "F",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "https://www.github.com/v1/docs/?q=1",
|
||||
host: "www.github.com",
|
||||
docPath: "/docs/",
|
||||
name: "G",
|
||||
basePath: "/v1",
|
||||
},
|
||||
{
|
||||
referer: "https://www.github.com/?q=1#tag=TAG",
|
||||
host: "www.github.com",
|
||||
docPath: "",
|
||||
name: "H",
|
||||
basePath: "",
|
||||
},
|
||||
{
|
||||
referer: "https://www.github.com/",
|
||||
host: "www.github.com",
|
||||
docPath: "/doc",
|
||||
name: "I",
|
||||
basePath: "/",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -141,14 +208,16 @@ func TestRefererHost(t *testing.T) {
|
||||
req.Header.Add("referer", tt.referer)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
if assert.NoError(t, r.(*Root).specHandler(tt.docPath)(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
var v struct {
|
||||
Host string `json:"host"`
|
||||
Host string `json:"host"`
|
||||
BasePath string `json:"basePath"`
|
||||
}
|
||||
err := json.Unmarshal(rec.Body.Bytes(), &v)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.host, v.Host)
|
||||
assert.Equal(t, tt.basePath, v.BasePath)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -181,7 +250,7 @@ func TestAddDefinition(t *testing.T) {
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).Spec(c)) {
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Len(t, r.(*Root).spec.Definitions, 2)
|
||||
}
|
||||
|
21
tag.go
21
tag.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
21
tag_test.go
21
tag_test.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
42
utils.go
42
utils.go
@ -1,6 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func contains(list []string, s string) bool {
|
||||
for _, t := range list {
|
||||
@ -85,3 +109,19 @@ func connectPath(paths ...string) string {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func removeTrailingSlash(path string) string {
|
||||
l := len(path) - 1
|
||||
if l > 0 && strings.HasSuffix(path, "/") {
|
||||
path = path[:l]
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func trimSuffixSlash(s, suffix string) string {
|
||||
s = connectPath(s)
|
||||
suffix = connectPath(suffix)
|
||||
s = removeTrailingSlash(s)
|
||||
suffix = removeTrailingSlash(suffix)
|
||||
return strings.TrimSuffix(s, suffix)
|
||||
}
|
||||
|
21
validator.go
21
validator.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
|
46
wrapper.go
46
wrapper.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
@ -5,18 +26,19 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
/*
|
||||
TODO:
|
||||
1.pattern
|
||||
2.opreationId 重复判断
|
||||
@TODO:
|
||||
1. pattern
|
||||
2. opreationId repeated
|
||||
|
||||
Notice:
|
||||
1.不会对Email和URL进行验证,因为不影响页面的正常显示
|
||||
2.SetSecurity/SetSecurityWithScope 传多个参数表示Security之间是AND关系;多次调用SetSecurity/SetSecurityWithScope Security之间是OR关系
|
||||
3.只支持基本类型的Map Key
|
||||
1. Email and URL will not be verified because it does not affect the normal display of the page
|
||||
2. SetSecurity / SetSecurityWithScope Pass multiple parameters to indicate that the security relationship is an AND relationship;
|
||||
multiple calls to SetSecurity / SetSecurityWithScope Security are an OR relationship
|
||||
3. Only support the basic type of Map Key
|
||||
*/
|
||||
|
||||
type ApiRouter interface {
|
||||
@ -67,6 +89,7 @@ type ApiRoot interface {
|
||||
AddSecurityOAuth2(name, desc string, flow OAuth2FlowType, authorizationUrl, tokenUrl string, scopes map[string]string) ApiRoot
|
||||
|
||||
// SetUI sets UI setting.
|
||||
// If DetachSpec is false, HideTop will not take effect
|
||||
SetUI(ui UISetting) ApiRoot
|
||||
|
||||
// SetScheme sets available protocol schemes.
|
||||
@ -209,7 +232,7 @@ type api struct {
|
||||
|
||||
// New creates ApiRoot instance.
|
||||
// Multiple ApiRoot are allowed in one project.
|
||||
func New(e *echo.Echo, basePath, docPath string, i *Info) ApiRoot {
|
||||
func New(e *echo.Echo, docPath string, i *Info) ApiRoot {
|
||||
if e == nil {
|
||||
panic("echoswagger: invalid Echo instance")
|
||||
}
|
||||
@ -225,7 +248,6 @@ func New(e *echo.Echo, basePath, docPath string, i *Info) ApiRoot {
|
||||
spec: &Swagger{
|
||||
Info: i,
|
||||
SecurityDefinitions: make(map[string]*SecurityDefinition),
|
||||
BasePath: connectPath(basePath),
|
||||
Definitions: make(map[string]*JSONSchema),
|
||||
},
|
||||
routers: routers{
|
||||
@ -233,10 +255,8 @@ func New(e *echo.Echo, basePath, docPath string, i *Info) ApiRoot {
|
||||
},
|
||||
}
|
||||
|
||||
specPath := connectPath(docPath, "swagger.json")
|
||||
realSpecPath := connectPath(basePath, specPath)
|
||||
e.GET(connectPath(docPath), r.docHandler(realSpecPath))
|
||||
e.GET(specPath, r.Spec)
|
||||
e.GET(connectPath(docPath), r.docHandler(docPath))
|
||||
e.GET(connectPath(docPath, SpecName), r.specHandler(docPath))
|
||||
return r
|
||||
}
|
||||
|
||||
|
164
wrapper_test.go
164
wrapper_test.go
@ -1,3 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @author Alex aka mailoman <alex@webz.asia>
|
||||
* @copyright Copyright (c) 2019 Alex aka mailoman <alex@webz.asia>
|
||||
* @since 18.12.2019
|
||||
*
|
||||
*/
|
||||
|
||||
package echoswagger
|
||||
|
||||
import (
|
||||
@ -7,12 +28,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func prepareApiRoot() ApiRoot {
|
||||
return New(echo.New(), "/", "doc/", nil)
|
||||
r := New(echo.New(), "doc/", nil)
|
||||
r.SetUI(UISetting{DetachSpec: true})
|
||||
return r
|
||||
}
|
||||
|
||||
func prepareApiGroup() ApiGroup {
|
||||
@ -29,7 +52,6 @@ func prepareApi() Api {
|
||||
func TestNew(t *testing.T) {
|
||||
tests := []struct {
|
||||
echo *echo.Echo
|
||||
basePath string
|
||||
docPath string
|
||||
info *Info
|
||||
expectPaths []string
|
||||
@ -38,7 +60,6 @@ func TestNew(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
echo: echo.New(),
|
||||
basePath: "/",
|
||||
docPath: "doc/",
|
||||
info: nil,
|
||||
expectPaths: []string{"/doc/", "/doc/swagger.json"},
|
||||
@ -46,13 +67,12 @@ func TestNew(t *testing.T) {
|
||||
name: "Normal",
|
||||
},
|
||||
{
|
||||
echo: echo.New(),
|
||||
basePath: "/",
|
||||
docPath: "doc",
|
||||
echo: echo.New(),
|
||||
docPath: "doc",
|
||||
info: &Info{
|
||||
Title: "Test project",
|
||||
Contact: &Contact{
|
||||
URL: "https://github.com/pangpanglabs/echoswagger",
|
||||
URL: "https://git.webz.asia/echo-go/echoswagger",
|
||||
},
|
||||
},
|
||||
expectPaths: []string{"/doc", "/doc/swagger.json"},
|
||||
@ -69,16 +89,15 @@ func TestNew(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.panic {
|
||||
assert.Panics(t, func() {
|
||||
New(tt.echo, tt.basePath, tt.docPath, tt.info)
|
||||
New(tt.echo, tt.docPath, tt.info)
|
||||
})
|
||||
} else {
|
||||
apiRoot := New(tt.echo, tt.basePath, tt.docPath, tt.info)
|
||||
apiRoot := New(tt.echo, tt.docPath, tt.info)
|
||||
assert.NotNil(t, apiRoot.(*Root))
|
||||
|
||||
r := apiRoot.(*Root)
|
||||
assert.NotNil(t, r.spec)
|
||||
|
||||
assert.Equal(t, r.spec.BasePath, tt.basePath)
|
||||
if tt.info == nil {
|
||||
assert.Equal(t, r.spec.Info.Title, "Project APIs")
|
||||
} else {
|
||||
@ -97,74 +116,36 @@ func TestNew(t *testing.T) {
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
tests := []struct {
|
||||
baseInput, docInput string
|
||||
baseOutput, docOutput, specOutput, realSpecOutput string
|
||||
name string
|
||||
docInput string
|
||||
docOutput, specOutput string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
baseInput: "/",
|
||||
docInput: "doc/",
|
||||
baseOutput: "/",
|
||||
docOutput: "/doc/",
|
||||
specOutput: "/doc/swagger.json",
|
||||
realSpecOutput: "/doc/swagger.json",
|
||||
name: "A",
|
||||
docInput: "doc/",
|
||||
docOutput: "/doc/",
|
||||
specOutput: "/doc/swagger.json",
|
||||
name: "A",
|
||||
}, {
|
||||
baseInput: "",
|
||||
docInput: "",
|
||||
baseOutput: "/",
|
||||
docOutput: "/",
|
||||
specOutput: "/swagger.json",
|
||||
realSpecOutput: "/swagger.json",
|
||||
name: "B",
|
||||
docInput: "",
|
||||
docOutput: "/",
|
||||
specOutput: "/swagger.json",
|
||||
name: "B",
|
||||
}, {
|
||||
baseInput: "/omni-api",
|
||||
docInput: "/doc",
|
||||
baseOutput: "/omni-api",
|
||||
docOutput: "/doc",
|
||||
specOutput: "/doc/swagger.json",
|
||||
realSpecOutput: "/omni-api/doc/swagger.json",
|
||||
name: "C",
|
||||
}, {
|
||||
baseInput: "/omni-api/",
|
||||
docInput: "",
|
||||
baseOutput: "/omni-api/",
|
||||
docOutput: "/",
|
||||
specOutput: "/swagger.json",
|
||||
realSpecOutput: "/omni-api/swagger.json",
|
||||
name: "D",
|
||||
}, {
|
||||
baseInput: "/omni-api",
|
||||
docInput: "doc/",
|
||||
baseOutput: "/omni-api",
|
||||
docOutput: "/doc/",
|
||||
specOutput: "/doc/swagger.json",
|
||||
realSpecOutput: "/omni-api/doc/swagger.json",
|
||||
name: "F",
|
||||
}, {
|
||||
baseInput: "omni-api",
|
||||
docInput: "doc/",
|
||||
baseOutput: "/omni-api",
|
||||
docOutput: "/doc/",
|
||||
specOutput: "/doc/swagger.json",
|
||||
realSpecOutput: "/omni-api/doc/swagger.json",
|
||||
name: "G",
|
||||
docInput: "/doc",
|
||||
docOutput: "/doc",
|
||||
specOutput: "/doc/swagger.json",
|
||||
name: "C",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
apiRoot := New(echo.New(), tt.baseInput, tt.docInput, nil)
|
||||
apiRoot := New(echo.New(), tt.docInput, nil)
|
||||
r := apiRoot.(*Root)
|
||||
|
||||
assert.Equal(t, r.spec.BasePath, tt.baseOutput)
|
||||
|
||||
assert.NotNil(t, r.echo)
|
||||
assert.Len(t, r.echo.Routes(), 2)
|
||||
res := r.echo.Routes()
|
||||
paths := []string{res[0].Path, res[1].Path}
|
||||
assert.ElementsMatch(t, paths, []string{tt.docOutput, tt.specOutput})
|
||||
|
||||
assert.Equal(t, tt.realSpecOutput, connectPath(tt.baseOutput, tt.specOutput))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -367,12 +348,12 @@ func TestAddResponse(t *testing.T) {
|
||||
|
||||
func TestUI(t *testing.T) {
|
||||
t.Run("DefaultCDN", func(t *testing.T) {
|
||||
r := New(echo.New(), "/", "doc/", nil)
|
||||
r := New(echo.New(), "doc/", nil)
|
||||
se := r.(*Root)
|
||||
req := httptest.NewRequest(echo.GET, "/doc/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := se.echo.NewContext(req, rec)
|
||||
h := se.docHandler("/doc/swagger.json")
|
||||
h := se.docHandler("doc/")
|
||||
|
||||
if assert.NoError(t, h(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
@ -381,12 +362,12 @@ func TestUI(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("SetUI", func(t *testing.T) {
|
||||
r := New(echo.New(), "/", "doc/", nil)
|
||||
r := New(echo.New(), "doc/", nil)
|
||||
se := r.(*Root)
|
||||
req := httptest.NewRequest(echo.GET, "/doc/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := se.echo.NewContext(req, rec)
|
||||
h := se.docHandler("/doc/swagger.json")
|
||||
h := se.docHandler("doc/")
|
||||
|
||||
cdn := "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.18.0"
|
||||
r.SetUI(UISetting{
|
||||
@ -397,6 +378,17 @@ func TestUI(t *testing.T) {
|
||||
if assert.NoError(t, h(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Contains(t, rec.Body.String(), cdn)
|
||||
assert.Contains(t, rec.Body.String(), `{\x22swagger\x22:`)
|
||||
assert.Contains(t, rec.Body.String(), "#swagger-ui>.swagger-container>.topbar")
|
||||
}
|
||||
|
||||
r.SetUI(UISetting{
|
||||
DetachSpec: true,
|
||||
})
|
||||
|
||||
if assert.NoError(t, h(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.NotContains(t, rec.Body.String(), "{\x22swagger\x22:")
|
||||
assert.Contains(t, rec.Body.String(), "#swagger-ui>.swagger-container>.topbar")
|
||||
}
|
||||
})
|
||||
@ -516,3 +508,37 @@ func TestEcho(t *testing.T) {
|
||||
a := prepareApi()
|
||||
assert.NotNil(t, a.Route())
|
||||
}
|
||||
|
||||
func TestHandlers(t *testing.T) {
|
||||
t.Run("ErrorGroupSecurity", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
var h echo.HandlerFunc
|
||||
r.Group("G", "/g").SetSecurity("JWT").GET("/", h)
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
if assert.NoError(t, r.(*Root).docHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ErrorApiSecurity", func(t *testing.T) {
|
||||
r := prepareApiRoot()
|
||||
e := r.(*Root).echo
|
||||
var h echo.HandlerFunc
|
||||
r.GET("/", h).SetSecurity("JWT")
|
||||
req := httptest.NewRequest(echo.GET, "/doc/swagger.json", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
c := e.NewContext(req, rec)
|
||||
if assert.NoError(t, r.(*Root).specHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
if assert.NoError(t, r.(*Root).docHandler("/doc")(c)) {
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user