mirror of
https://github.com/datarhei/core.git
synced 2025-10-10 10:20:06 +08:00
Add GoSRT & improvements (repo-merge)
Commits (Ingo Oppermann): - Add experimental SRT connection stats and logs - Hide /config/reload endpoint in reade-only mode - Add SRT server - Create v16 in go.mod - Fix data races, tests, lint, and update dependencies - Add trailing slash for routed directories (datarhei/restreamer#340) - Allow relative URLs in content in static routes Co-Authored-By: Ingo Oppermann <57445+ioppermann@users.noreply.github.com>
This commit is contained in:
2
vendor/github.com/swaggo/swag/Dockerfile
generated
vendored
2
vendor/github.com/swaggo/swag/Dockerfile
generated
vendored
@@ -1,7 +1,7 @@
|
||||
# Dockerfile References: https://docs.docker.com/engine/reference/builder/
|
||||
|
||||
# Start from the latest golang base image
|
||||
FROM golang:1.17-alpine as builder
|
||||
FROM golang:1.18.3-alpine as builder
|
||||
|
||||
# Set the Current Working Directory inside the container
|
||||
WORKDIR /app
|
||||
|
2
vendor/github.com/swaggo/swag/README_zh-CN.md
generated
vendored
2
vendor/github.com/swaggo/swag/README_zh-CN.md
generated
vendored
@@ -63,7 +63,7 @@ $ go install github.com/swaggo/swag/cmd/swag@latest
|
||||
swag init
|
||||
```
|
||||
|
||||
确保导入了生成的`docs/docs.go`文件,这样特定的配置文件才会被初始化。如果通用API指数没有写在`main.go`中,可以使用`-g`标识符来告知swag。
|
||||
确保导入了生成的`docs/docs.go`文件,这样特定的配置文件才会被初始化。如果通用API注释没有写在`main.go`中,可以使用`-g`标识符来告知swag。
|
||||
|
||||
```bash
|
||||
swag init -g http/api.go
|
||||
|
18
vendor/github.com/swaggo/swag/field_parser.go
generated
vendored
18
vendor/github.com/swaggo/swag/field_parser.go
generated
vendored
@@ -388,10 +388,6 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
|
||||
|
||||
varNamesTag := ps.tag.Get("x-enum-varnames")
|
||||
if varNamesTag != "" {
|
||||
if schema.Extensions == nil {
|
||||
schema.Extensions = map[string]interface{}{}
|
||||
}
|
||||
|
||||
varNames := strings.Split(varNamesTag, ",")
|
||||
if len(varNames) != len(field.enums) {
|
||||
return fmt.Errorf("invalid count of x-enum-varnames. expected %d, got %d", len(field.enums), len(varNames))
|
||||
@@ -403,7 +399,19 @@ func (ps *tagBaseFieldParser) ComplementSchema(schema *spec.Schema) error {
|
||||
field.enumVarNames = append(field.enumVarNames, v)
|
||||
}
|
||||
|
||||
schema.Extensions["x-enum-varnames"] = field.enumVarNames
|
||||
if field.schemaType == ARRAY {
|
||||
// Add the var names in the items schema
|
||||
if schema.Items.Schema.Extensions == nil {
|
||||
schema.Items.Schema.Extensions = map[string]interface{}{}
|
||||
}
|
||||
schema.Items.Schema.Extensions["x-enum-varnames"] = field.enumVarNames
|
||||
} else {
|
||||
// Add to top level schema
|
||||
if schema.Extensions == nil {
|
||||
schema.Extensions = map[string]interface{}{}
|
||||
}
|
||||
schema.Extensions["x-enum-varnames"] = field.enumVarNames
|
||||
}
|
||||
}
|
||||
|
||||
eleSchema := schema
|
||||
|
109
vendor/github.com/swaggo/swag/generics.go
generated
vendored
Normal file
109
vendor/github.com/swaggo/swag/generics.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package swag
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func typeSpecFullName(typeSpecDef *TypeSpecDef) string {
|
||||
fullName := typeSpecDef.FullName()
|
||||
|
||||
if typeSpecDef.TypeSpec.TypeParams != nil {
|
||||
fullName = fullName + "["
|
||||
for i, typeParam := range typeSpecDef.TypeSpec.TypeParams.List {
|
||||
if i > 0 {
|
||||
fullName = fullName + "-"
|
||||
}
|
||||
|
||||
fullName = fullName + typeParam.Names[0].Name
|
||||
}
|
||||
fullName = fullName + "]"
|
||||
}
|
||||
|
||||
return fullName
|
||||
}
|
||||
|
||||
func (pkgDefs *PackagesDefinitions) parametrizeStruct(original *TypeSpecDef, fullGenericForm string) *TypeSpecDef {
|
||||
genericParams := strings.Split(strings.TrimRight(fullGenericForm, "]"), "[")
|
||||
if len(genericParams) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
genericParams = strings.Split(genericParams[1], ",")
|
||||
for i, p := range genericParams {
|
||||
genericParams[i] = strings.TrimSpace(p)
|
||||
}
|
||||
genericParamTypeDefs := map[string]*TypeSpecDef{}
|
||||
|
||||
if len(genericParams) != len(original.TypeSpec.TypeParams.List) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, genericParam := range genericParams {
|
||||
tdef, ok := pkgDefs.uniqueDefinitions[genericParam]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
genericParamTypeDefs[original.TypeSpec.TypeParams.List[i].Names[0].Name] = tdef
|
||||
}
|
||||
|
||||
parametrizedTypeSpec := &TypeSpecDef{
|
||||
File: original.File,
|
||||
PkgPath: original.PkgPath,
|
||||
TypeSpec: &ast.TypeSpec{
|
||||
Doc: original.TypeSpec.Doc,
|
||||
Comment: original.TypeSpec.Comment,
|
||||
Assign: original.TypeSpec.Assign,
|
||||
},
|
||||
}
|
||||
|
||||
ident := &ast.Ident{
|
||||
NamePos: original.TypeSpec.Name.NamePos,
|
||||
Obj: original.TypeSpec.Name.Obj,
|
||||
}
|
||||
|
||||
genNameParts := strings.Split(fullGenericForm, "[")
|
||||
if strings.Contains(genNameParts[0], ".") {
|
||||
genNameParts[0] = strings.Split(genNameParts[0], ".")[1]
|
||||
}
|
||||
|
||||
ident.Name = genNameParts[0] + "-" + strings.Replace(strings.Join(genericParams, "-"), ".", "_", -1)
|
||||
ident.Name = strings.Replace(strings.Replace(ident.Name, "\t", "", -1), " ", "", -1)
|
||||
|
||||
parametrizedTypeSpec.TypeSpec.Name = ident
|
||||
|
||||
origStructType := original.TypeSpec.Type.(*ast.StructType)
|
||||
|
||||
newStructTypeDef := &ast.StructType{
|
||||
Struct: origStructType.Struct,
|
||||
Incomplete: origStructType.Incomplete,
|
||||
Fields: &ast.FieldList{
|
||||
Opening: origStructType.Fields.Opening,
|
||||
Closing: origStructType.Fields.Closing,
|
||||
},
|
||||
}
|
||||
|
||||
for _, field := range origStructType.Fields.List {
|
||||
newField := &ast.Field{
|
||||
Doc: field.Doc,
|
||||
Names: field.Names,
|
||||
Tag: field.Tag,
|
||||
Comment: field.Comment,
|
||||
}
|
||||
if genTypeSpec, ok := genericParamTypeDefs[field.Type.(*ast.Ident).Name]; ok {
|
||||
newField.Type = genTypeSpec.TypeSpec.Type
|
||||
} else {
|
||||
newField.Type = field.Type
|
||||
}
|
||||
|
||||
newStructTypeDef.Fields.List = append(newStructTypeDef.Fields.List, newField)
|
||||
}
|
||||
|
||||
parametrizedTypeSpec.TypeSpec.Type = newStructTypeDef
|
||||
|
||||
return parametrizedTypeSpec
|
||||
}
|
12
vendor/github.com/swaggo/swag/generics_other.go
generated
vendored
Normal file
12
vendor/github.com/swaggo/swag/generics_other.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package swag
|
||||
|
||||
func typeSpecFullName(typeSpecDef *TypeSpecDef) string {
|
||||
return typeSpecDef.FullName()
|
||||
}
|
||||
|
||||
func (pkgDefs *PackagesDefinitions) parametrizeStruct(original *TypeSpecDef, fullGenericForm string) *TypeSpecDef {
|
||||
return original
|
||||
}
|
74
vendor/github.com/swaggo/swag/golist.go
generated
vendored
Normal file
74
vendor/github.com/swaggo/swag/golist.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package swag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func listPackages(ctx context.Context, dir string, env []string, args ...string) (pkgs []*build.Package, finalErr error) {
|
||||
cmd := exec.CommandContext(ctx, "go", append([]string{"list", "-json", "-e"}, args...)...)
|
||||
cmd.Env = env
|
||||
cmd.Dir = dir
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var stderrBuf bytes.Buffer
|
||||
cmd.Stderr = &stderrBuf
|
||||
defer func() {
|
||||
if stderrBuf.Len() > 0 {
|
||||
finalErr = fmt.Errorf("%v\n%s", finalErr, stderrBuf.Bytes())
|
||||
}
|
||||
}()
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dec := json.NewDecoder(stdout)
|
||||
for dec.More() {
|
||||
var pkg build.Package
|
||||
err = dec.Decode(&pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkgs = append(pkgs, &pkg)
|
||||
}
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func (parser *Parser) getAllGoFileInfoFromDepsByList(pkg *build.Package) error {
|
||||
ignoreInternal := pkg.Goroot && !parser.ParseInternal
|
||||
if ignoreInternal { // ignored internal
|
||||
return nil
|
||||
}
|
||||
|
||||
srcDir := pkg.Dir
|
||||
var err error
|
||||
for i := range pkg.GoFiles {
|
||||
err = parser.parseFile(pkg.ImportPath, filepath.Join(srcDir, pkg.GoFiles[i]), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// parse .go source files that import "C"
|
||||
for i := range pkg.CgoFiles {
|
||||
err = parser.parseFile(pkg.ImportPath, filepath.Join(srcDir, pkg.CgoFiles[i]), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
15
vendor/github.com/swaggo/swag/operation.go
generated
vendored
15
vendor/github.com/swaggo/swag/operation.go
generated
vendored
@@ -385,7 +385,7 @@ func (operation *Operation) ParseParamComment(commentLine string, astFile *ast.F
|
||||
if objectType == PRIMITIVE {
|
||||
param.Schema = PrimitiveSchema(refType)
|
||||
} else {
|
||||
schema, err := operation.parseAPIObjectSchema(objectType, refType, astFile)
|
||||
schema, err := operation.parseAPIObjectSchema(commentLine, objectType, refType, astFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -933,7 +933,16 @@ func (operation *Operation) parseCombinedObjectSchema(refType string, astFile *a
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (operation *Operation) parseAPIObjectSchema(schemaType, refType string, astFile *ast.File) (*spec.Schema, error) {
|
||||
func (operation *Operation) parseAPIObjectSchema(commentLine, schemaType, refType string, astFile *ast.File) (*spec.Schema, error) {
|
||||
if strings.HasSuffix(refType, ",") && strings.Contains(refType, "[") {
|
||||
// regexp may have broken generics syntax. find closing bracket and add it back
|
||||
allMatchesLenOffset := strings.Index(commentLine, refType) + len(refType)
|
||||
lostPartEndIdx := strings.Index(commentLine[allMatchesLenOffset:], "]")
|
||||
if lostPartEndIdx >= 0 {
|
||||
refType += commentLine[allMatchesLenOffset : allMatchesLenOffset+lostPartEndIdx+1]
|
||||
}
|
||||
}
|
||||
|
||||
switch schemaType {
|
||||
case OBJECT:
|
||||
if !strings.HasPrefix(refType, "[]") {
|
||||
@@ -969,7 +978,7 @@ func (operation *Operation) ParseResponseComment(commentLine string, astFile *as
|
||||
|
||||
description := strings.Trim(matches[4], "\"")
|
||||
|
||||
schema, err := operation.parseAPIObjectSchema(strings.Trim(matches[2], "{}"), matches[3], astFile)
|
||||
schema, err := operation.parseAPIObjectSchema(commentLine, strings.Trim(matches[2], "{}"), matches[3], astFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
27
vendor/github.com/swaggo/swag/packages.go
generated
vendored
27
vendor/github.com/swaggo/swag/packages.go
generated
vendored
@@ -6,6 +6,7 @@ import (
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -78,6 +79,11 @@ func (pkgDefs *PackagesDefinitions) CollectAstFile(packageDir, path string, astF
|
||||
func rangeFiles(files map[*ast.File]*AstFileInfo, handle func(filename string, file *ast.File) error) error {
|
||||
sortedFiles := make([]*AstFileInfo, 0, len(files))
|
||||
for _, info := range files {
|
||||
// ignore package path prefix with 'vendor' or $GOROOT,
|
||||
// because the router info of api will not be included these files.
|
||||
if strings.HasPrefix(info.PackagePath, "vendor") || strings.HasPrefix(info.Path, runtime.GOROOT()) {
|
||||
continue
|
||||
}
|
||||
sortedFiles = append(sortedFiles, info)
|
||||
}
|
||||
|
||||
@@ -128,7 +134,8 @@ func (pkgDefs *PackagesDefinitions) parseTypesFromFile(astFile *ast.File, packag
|
||||
pkgDefs.uniqueDefinitions = make(map[string]*TypeSpecDef)
|
||||
}
|
||||
|
||||
fullName := typeSpecDef.FullName()
|
||||
fullName := typeSpecFullName(typeSpecDef)
|
||||
|
||||
anotherTypeDef, ok := pkgDefs.uniqueDefinitions[fullName]
|
||||
if ok {
|
||||
if typeSpecDef.PkgPath == anotherTypeDef.PkgPath {
|
||||
@@ -286,7 +293,7 @@ func (pkgDefs *PackagesDefinitions) FindTypeSpec(typeName string, file *ast.File
|
||||
return pkgDefs.uniqueDefinitions[typeName]
|
||||
}
|
||||
|
||||
parts := strings.Split(typeName, ".")
|
||||
parts := strings.Split(strings.Split(typeName, "[")[0], ".")
|
||||
if len(parts) > 1 {
|
||||
isAliasPkgName := func(file *ast.File, pkgName string) bool {
|
||||
if file != nil && file.Imports != nil {
|
||||
@@ -322,6 +329,22 @@ func (pkgDefs *PackagesDefinitions) FindTypeSpec(typeName string, file *ast.File
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(typeName, "[") {
|
||||
// joinedParts differs from typeName in that it does not contain any type parameters
|
||||
joinedParts := strings.Join(parts, ".")
|
||||
for tName, tSpec := range pkgDefs.uniqueDefinitions {
|
||||
if !strings.Contains(tName, "[") {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(tName, joinedParts) {
|
||||
if parametrized := pkgDefs.parametrizeStruct(tSpec, typeName); parametrized != nil {
|
||||
return parametrized
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgDefs.findTypeSpec(pkgPath, parts[1])
|
||||
}
|
||||
|
||||
|
408
vendor/github.com/swaggo/swag/parser.go
generated
vendored
408
vendor/github.com/swaggo/swag/parser.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package swag
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -48,9 +49,21 @@ const (
|
||||
deprecatedAttr = "@deprecated"
|
||||
securityAttr = "@security"
|
||||
titleAttr = "@title"
|
||||
conNameAttr = "@contact.name"
|
||||
conURLAttr = "@contact.url"
|
||||
conEmailAttr = "@contact.email"
|
||||
licNameAttr = "@license.name"
|
||||
licURLAttr = "@license.url"
|
||||
versionAttr = "@version"
|
||||
descriptionAttr = "@description"
|
||||
descriptionMarkdownAttr = "@description.markdown"
|
||||
secBasicAttr = "@securitydefinitions.basic"
|
||||
secAPIKeyAttr = "@securitydefinitions.apikey"
|
||||
secApplicationAttr = "@securitydefinitions.oauth2.application"
|
||||
secImplicitAttr = "@securitydefinitions.oauth2.implicit"
|
||||
secPasswordAttr = "@securitydefinitions.oauth2.password"
|
||||
secAccessCodeAttr = "@securitydefinitions.oauth2.accesscode"
|
||||
tosAttr = "@termsofservice"
|
||||
xCodeSamplesAttr = "@x-codesamples"
|
||||
scopeAttrPrefix = "@scope."
|
||||
)
|
||||
@@ -140,6 +153,9 @@ type Parser struct {
|
||||
|
||||
// Overrides allows global replacements of types. A blank replacement will be skipped.
|
||||
Overrides map[string]string
|
||||
|
||||
// parseGoList whether swag use go list to parse dependency
|
||||
parseGoList bool
|
||||
}
|
||||
|
||||
// FieldParserFactory create FieldParser.
|
||||
@@ -241,7 +257,10 @@ func SetStrict(strict bool) func(*Parser) {
|
||||
// SetDebugger allows the use of user-defined implementations.
|
||||
func SetDebugger(logger Debugger) func(parser *Parser) {
|
||||
return func(p *Parser) {
|
||||
p.debug = logger
|
||||
if logger != nil {
|
||||
p.debug = logger
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +280,13 @@ func SetOverrides(overrides map[string]string) func(parser *Parser) {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseUsingGoList sets whether swag use go list to parse dependency
|
||||
func ParseUsingGoList(enabled bool) func(parser *Parser) {
|
||||
return func(p *Parser) {
|
||||
p.parseGoList = enabled
|
||||
}
|
||||
}
|
||||
|
||||
// ParseAPI parses general api info for given searchDir and mainAPIFile.
|
||||
func (parser *Parser) ParseAPI(searchDir string, mainAPIFile string, parseDepth int) error {
|
||||
return parser.ParseAPIMultiSearchDir([]string{searchDir}, mainAPIFile, parseDepth)
|
||||
@@ -287,26 +313,41 @@ func (parser *Parser) ParseAPIMultiSearchDir(searchDirs []string, mainAPIFile st
|
||||
return err
|
||||
}
|
||||
|
||||
// Use 'go list' command instead of depth.Resolve()
|
||||
if parser.ParseDependency {
|
||||
var tree depth.Tree
|
||||
tree.ResolveInternal = true
|
||||
tree.MaxDepth = parseDepth
|
||||
if parser.parseGoList {
|
||||
pkgs, err := listPackages(context.Background(), filepath.Dir(absMainAPIFilePath), nil, "-deps")
|
||||
if err != nil {
|
||||
return fmt.Errorf("pkg %s cannot find all dependencies, %s", filepath.Dir(absMainAPIFilePath), err)
|
||||
}
|
||||
|
||||
pkgName, err := getPkgName(filepath.Dir(absMainAPIFilePath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
length := len(pkgs)
|
||||
for i := 0; i < length; i++ {
|
||||
err := parser.getAllGoFileInfoFromDepsByList(pkgs[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var t depth.Tree
|
||||
t.ResolveInternal = true
|
||||
t.MaxDepth = parseDepth
|
||||
|
||||
err = tree.Resolve(pkgName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pkg %s cannot find all dependencies, %s", pkgName, err)
|
||||
}
|
||||
|
||||
for i := 0; i < len(tree.Root.Deps); i++ {
|
||||
err := parser.getAllGoFileInfoFromDeps(&tree.Root.Deps[i])
|
||||
pkgName, err := getPkgName(filepath.Dir(absMainAPIFilePath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = t.Resolve(pkgName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pkg %s cannot find all dependencies, %s", pkgName, err)
|
||||
}
|
||||
for i := 0; i < len(t.Root.Deps); i++ {
|
||||
err := parser.getAllGoFileInfoFromDeps(&t.Root.Deps[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,14 +397,6 @@ func getPkgName(searchDir string) (string, error) {
|
||||
return outStr, nil
|
||||
}
|
||||
|
||||
func initIfEmpty(license *spec.License) *spec.License {
|
||||
if license == nil {
|
||||
return new(spec.License)
|
||||
}
|
||||
|
||||
return license
|
||||
}
|
||||
|
||||
// ParseGeneralAPIInfo parses general api info for given mainAPIFile path.
|
||||
func (parser *Parser) ParseGeneralAPIInfo(mainAPIFile string) error {
|
||||
fileTree, err := goparser.ParseFile(token.NewFileSet(), mainAPIFile, nil, goparser.ParseComments)
|
||||
@@ -396,16 +429,15 @@ func parseGeneralAPIInfo(parser *Parser, comments []string) error {
|
||||
commentLine := comments[line]
|
||||
attribute := strings.Split(commentLine, " ")[0]
|
||||
value := strings.TrimSpace(commentLine[len(attribute):])
|
||||
|
||||
multilineBlock := false
|
||||
if previousAttribute == attribute {
|
||||
multilineBlock = true
|
||||
}
|
||||
|
||||
switch strings.ToLower(attribute) {
|
||||
case versionAttr:
|
||||
parser.swagger.Info.Version = value
|
||||
case titleAttr:
|
||||
parser.swagger.Info.Title = value
|
||||
switch attr := strings.ToLower(attribute); attr {
|
||||
case versionAttr, titleAttr, tosAttr, licNameAttr, licURLAttr, conNameAttr, conURLAttr, conEmailAttr:
|
||||
setSwaggerInfo(parser.swagger, attr, value)
|
||||
case descriptionAttr:
|
||||
if multilineBlock {
|
||||
parser.swagger.Info.Description += "\n" + value
|
||||
@@ -413,32 +445,20 @@ func parseGeneralAPIInfo(parser *Parser, comments []string) error {
|
||||
continue
|
||||
}
|
||||
|
||||
parser.swagger.Info.Description = value
|
||||
case "@description.markdown":
|
||||
setSwaggerInfo(parser.swagger, attr, value)
|
||||
case descriptionMarkdownAttr:
|
||||
commentInfo, err := getMarkdownForTag("api", parser.markdownFileDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parser.swagger.Info.Description = string(commentInfo)
|
||||
case "@termsofservice":
|
||||
parser.swagger.Info.TermsOfService = value
|
||||
case "@contact.name":
|
||||
parser.swagger.Info.Contact.Name = value
|
||||
case "@contact.email":
|
||||
parser.swagger.Info.Contact.Email = value
|
||||
case "@contact.url":
|
||||
parser.swagger.Info.Contact.URL = value
|
||||
case "@license.name":
|
||||
parser.swagger.Info.License = initIfEmpty(parser.swagger.Info.License)
|
||||
parser.swagger.Info.License.Name = value
|
||||
case "@license.url":
|
||||
parser.swagger.Info.License = initIfEmpty(parser.swagger.Info.License)
|
||||
parser.swagger.Info.License.URL = value
|
||||
setSwaggerInfo(parser.swagger, descriptionAttr, string(commentInfo))
|
||||
|
||||
case "@host":
|
||||
parser.swagger.Host = value
|
||||
case "@basepath":
|
||||
parser.swagger.BasePath = value
|
||||
|
||||
case acceptAttr:
|
||||
err := parser.ParseAcceptComment(value)
|
||||
if err != nil {
|
||||
@@ -450,7 +470,7 @@ func parseGeneralAPIInfo(parser *Parser, comments []string) error {
|
||||
return err
|
||||
}
|
||||
case "@schemes":
|
||||
parser.swagger.Schemes = getSchemes(commentLine)
|
||||
parser.swagger.Schemes = strings.Split(value, " ")
|
||||
case "@tag.name":
|
||||
parser.swagger.Tags = append(parser.swagger.Tags, spec.Tag{
|
||||
TagProps: spec.TagProps{
|
||||
@@ -487,43 +507,15 @@ func parseGeneralAPIInfo(parser *Parser, comments []string) error {
|
||||
|
||||
tag.TagProps.ExternalDocs.Description = value
|
||||
replaceLastTag(parser.swagger.Tags, tag)
|
||||
case "@securitydefinitions.basic":
|
||||
parser.swagger.SecurityDefinitions[value] = spec.BasicAuth()
|
||||
case "@securitydefinitions.apikey":
|
||||
attrMap, _, extensions, err := parseSecAttr(attribute, []string{"@in", "@name"}, comments, &line)
|
||||
|
||||
case secBasicAttr, secAPIKeyAttr, secApplicationAttr, secImplicitAttr, secPasswordAttr, secAccessCodeAttr:
|
||||
scheme, err := parseSecAttributes(attribute, comments, &line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parser.swagger.SecurityDefinitions[value] = tryAddDescription(spec.APIKeyAuth(attrMap["@name"], attrMap["@in"]), extensions)
|
||||
case "@securitydefinitions.oauth2.application":
|
||||
attrMap, scopes, extensions, err := parseSecAttr(attribute, []string{"@tokenurl"}, comments, &line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
parser.swagger.SecurityDefinitions[value] = scheme
|
||||
|
||||
parser.swagger.SecurityDefinitions[value] = tryAddDescription(secOAuth2Application(attrMap["@tokenurl"], scopes, extensions), extensions)
|
||||
case "@securitydefinitions.oauth2.implicit":
|
||||
attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@authorizationurl"}, comments, &line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parser.swagger.SecurityDefinitions[value] = tryAddDescription(secOAuth2Implicit(attrs["@authorizationurl"], scopes, ext), ext)
|
||||
case "@securitydefinitions.oauth2.password":
|
||||
attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@tokenurl"}, comments, &line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parser.swagger.SecurityDefinitions[value] = tryAddDescription(secOAuth2Password(attrs["@tokenurl"], scopes, ext), ext)
|
||||
case "@securitydefinitions.oauth2.accesscode":
|
||||
attrs, scopes, ext, err := parseSecAttr(attribute, []string{"@tokenurl", "@authorizationurl"}, comments, &line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parser.swagger.SecurityDefinitions[value] = tryAddDescription(secOAuth2AccessToken(attrs["@authorizationurl"], attrs["@tokenurl"], scopes, ext), ext)
|
||||
case "@query.collection.format":
|
||||
parser.collectionFormatInQuery = value
|
||||
default:
|
||||
@@ -578,14 +570,140 @@ func parseGeneralAPIInfo(parser *Parser, comments []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func tryAddDescription(spec *spec.SecurityScheme, extensions map[string]interface{}) *spec.SecurityScheme {
|
||||
if val, ok := extensions["@description"]; ok {
|
||||
if str, ok := val.(string); ok {
|
||||
spec.Description = str
|
||||
func setSwaggerInfo(swagger *spec.Swagger, attribute, value string) {
|
||||
switch attribute {
|
||||
case versionAttr:
|
||||
swagger.Info.Version = value
|
||||
case titleAttr:
|
||||
swagger.Info.Title = value
|
||||
case tosAttr:
|
||||
swagger.Info.TermsOfService = value
|
||||
case descriptionAttr:
|
||||
swagger.Info.Description = value
|
||||
case conNameAttr:
|
||||
swagger.Info.Contact.Name = value
|
||||
case conEmailAttr:
|
||||
swagger.Info.Contact.Email = value
|
||||
case conURLAttr:
|
||||
swagger.Info.Contact.URL = value
|
||||
case licNameAttr:
|
||||
swagger.Info.License = initIfEmpty(swagger.Info.License)
|
||||
swagger.Info.License.Name = value
|
||||
case licURLAttr:
|
||||
swagger.Info.License = initIfEmpty(swagger.Info.License)
|
||||
swagger.Info.License.URL = value
|
||||
}
|
||||
}
|
||||
|
||||
func parseSecAttributes(context string, lines []string, index *int) (*spec.SecurityScheme, error) {
|
||||
const (
|
||||
in = "@in"
|
||||
name = "@name"
|
||||
descriptionAttr = "@description"
|
||||
tokenURL = "@tokenurl"
|
||||
authorizationURL = "@authorizationurl"
|
||||
)
|
||||
|
||||
var search []string
|
||||
|
||||
attribute := strings.ToLower(strings.Split(lines[*index], " ")[0])
|
||||
switch attribute {
|
||||
case secBasicAttr:
|
||||
return spec.BasicAuth(), nil
|
||||
case secAPIKeyAttr:
|
||||
search = []string{in, name}
|
||||
case secApplicationAttr, secPasswordAttr:
|
||||
search = []string{tokenURL}
|
||||
case secImplicitAttr:
|
||||
search = []string{authorizationURL}
|
||||
case secAccessCodeAttr:
|
||||
search = []string{tokenURL, authorizationURL}
|
||||
}
|
||||
|
||||
// For the first line we get the attributes in the context parameter, so we skip to the next one
|
||||
*index++
|
||||
|
||||
attrMap, scopes := make(map[string]string), make(map[string]string)
|
||||
extensions, description := make(map[string]interface{}), ""
|
||||
|
||||
for ; *index < len(lines); *index++ {
|
||||
v := lines[*index]
|
||||
|
||||
securityAttr := strings.ToLower(strings.Split(v, " ")[0])
|
||||
for _, findterm := range search {
|
||||
if securityAttr == findterm {
|
||||
attrMap[securityAttr] = strings.TrimSpace(v[len(securityAttr):])
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
isExists, err := isExistsScope(securityAttr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isExists {
|
||||
scopes[securityAttr[len(scopeAttrPrefix):]] = v[len(securityAttr):]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(securityAttr, "@x-") {
|
||||
// Add the custom attribute without the @
|
||||
extensions[securityAttr[1:]] = strings.TrimSpace(v[len(securityAttr):])
|
||||
}
|
||||
|
||||
// Not mandatory field
|
||||
if securityAttr == descriptionAttr {
|
||||
description = strings.TrimSpace(v[len(securityAttr):])
|
||||
}
|
||||
|
||||
// next securityDefinitions
|
||||
if strings.Index(securityAttr, "@securitydefinitions.") == 0 {
|
||||
// Go back to the previous line and break
|
||||
*index--
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return spec
|
||||
if len(attrMap) != len(search) {
|
||||
return nil, fmt.Errorf("%s is %v required", context, search)
|
||||
}
|
||||
|
||||
var scheme *spec.SecurityScheme
|
||||
|
||||
switch attribute {
|
||||
case secAPIKeyAttr:
|
||||
scheme = spec.APIKeyAuth(attrMap[name], attrMap[in])
|
||||
case secApplicationAttr:
|
||||
scheme = spec.OAuth2Application(attrMap[tokenURL])
|
||||
case secImplicitAttr:
|
||||
scheme = spec.OAuth2Implicit(attrMap[authorizationURL])
|
||||
case secPasswordAttr:
|
||||
scheme = spec.OAuth2Password(attrMap[tokenURL])
|
||||
case secAccessCodeAttr:
|
||||
scheme = spec.OAuth2AccessToken(attrMap[authorizationURL], attrMap[tokenURL])
|
||||
}
|
||||
|
||||
scheme.Description = description
|
||||
|
||||
for extKey, extValue := range extensions {
|
||||
scheme.AddExtension(extKey, extValue)
|
||||
}
|
||||
|
||||
for scope, scopeDescription := range scopes {
|
||||
scheme.AddScope(scope, scopeDescription)
|
||||
}
|
||||
|
||||
return scheme, nil
|
||||
}
|
||||
|
||||
func initIfEmpty(license *spec.License) *spec.License {
|
||||
if license == nil {
|
||||
return new(spec.License)
|
||||
}
|
||||
|
||||
return license
|
||||
}
|
||||
|
||||
// ParseAcceptComment parses comment for given `accept` comment string.
|
||||
@@ -611,121 +729,6 @@ func isGeneralAPIComment(comments []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func parseSecAttr(context string, search []string, lines []string, index *int) (map[string]string, map[string]string, map[string]interface{}, error) {
|
||||
attrMap := map[string]string{}
|
||||
scopes := map[string]string{}
|
||||
extensions := map[string]interface{}{}
|
||||
|
||||
// For the first line we get the attributes in the context parameter, so we skip to the next one
|
||||
*index++
|
||||
|
||||
for ; *index < len(lines); *index++ {
|
||||
v := lines[*index]
|
||||
|
||||
securityAttr := strings.ToLower(strings.Split(v, " ")[0])
|
||||
for _, findterm := range search {
|
||||
if securityAttr == findterm {
|
||||
attrMap[securityAttr] = strings.TrimSpace(v[len(securityAttr):])
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
isExists, err := isExistsScope(securityAttr)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if isExists {
|
||||
scopes[securityAttr[len(scopeAttrPrefix):]] = v[len(securityAttr):]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(securityAttr, "@x-") {
|
||||
// Add the custom attribute without the @
|
||||
extensions[securityAttr[1:]] = strings.TrimSpace(v[len(securityAttr):])
|
||||
}
|
||||
|
||||
// Not mandatory field
|
||||
if securityAttr == "@description" {
|
||||
extensions[securityAttr] = strings.TrimSpace(v[len(securityAttr):])
|
||||
}
|
||||
|
||||
// next securityDefinitions
|
||||
if strings.Index(securityAttr, "@securitydefinitions.") == 0 {
|
||||
// Go back to the previous line and break
|
||||
*index--
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(attrMap) != len(search) {
|
||||
return nil, nil, nil, fmt.Errorf("%s is %v required", context, search)
|
||||
}
|
||||
|
||||
return attrMap, scopes, extensions, nil
|
||||
}
|
||||
|
||||
type (
|
||||
authExtensions map[string]interface{}
|
||||
authScopes map[string]string
|
||||
)
|
||||
|
||||
func secOAuth2Application(tokenURL string, scopes authScopes, extensions authExtensions) *spec.SecurityScheme {
|
||||
securityScheme := spec.OAuth2Application(tokenURL)
|
||||
securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions)
|
||||
for scope, description := range scopes {
|
||||
securityScheme.AddScope(scope, description)
|
||||
}
|
||||
|
||||
return securityScheme
|
||||
}
|
||||
|
||||
func secOAuth2Implicit(authorizationURL string, scopes authScopes, extensions authExtensions) *spec.SecurityScheme {
|
||||
securityScheme := spec.OAuth2Implicit(authorizationURL)
|
||||
securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions)
|
||||
|
||||
for scope, description := range scopes {
|
||||
securityScheme.AddScope(scope, description)
|
||||
}
|
||||
|
||||
return securityScheme
|
||||
}
|
||||
|
||||
func secOAuth2Password(tokenURL string, scopes authScopes, extensions authExtensions) *spec.SecurityScheme {
|
||||
securityScheme := spec.OAuth2Password(tokenURL)
|
||||
securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions)
|
||||
|
||||
for scope, description := range scopes {
|
||||
securityScheme.AddScope(scope, description)
|
||||
}
|
||||
|
||||
return securityScheme
|
||||
}
|
||||
|
||||
func secOAuth2AccessToken(authorizationURL, tokenURL string, scopes authScopes, extensions authExtensions) *spec.SecurityScheme {
|
||||
securityScheme := spec.OAuth2AccessToken(authorizationURL, tokenURL)
|
||||
securityScheme.VendorExtensible.Extensions = handleSecuritySchemaExtensions(extensions)
|
||||
|
||||
for scope, description := range scopes {
|
||||
securityScheme.AddScope(scope, description)
|
||||
}
|
||||
|
||||
return securityScheme
|
||||
}
|
||||
|
||||
func handleSecuritySchemaExtensions(providedExtensions authExtensions) spec.Extensions {
|
||||
var extensions spec.Extensions
|
||||
if len(providedExtensions) > 0 {
|
||||
extensions = make(map[string]interface{}, len(providedExtensions))
|
||||
for key, value := range providedExtensions {
|
||||
extensions[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return extensions
|
||||
}
|
||||
|
||||
func getMarkdownForTag(tagName string, dirPath string) ([]byte, error) {
|
||||
filesInfos, err := ioutil.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
@@ -771,13 +774,6 @@ func isExistsScope(scope string) (bool, error) {
|
||||
return strings.Contains(scope, scopeAttrPrefix), nil
|
||||
}
|
||||
|
||||
// getSchemes parses swagger schemes for given commentLine.
|
||||
func getSchemes(commentLine string) []string {
|
||||
attribute := strings.ToLower(strings.Split(commentLine, " ")[0])
|
||||
|
||||
return strings.Split(strings.TrimSpace(commentLine[len(attribute):]), " ")
|
||||
}
|
||||
|
||||
// ParseRouterAPIInfo parses router api info for given astFile.
|
||||
func (parser *Parser) ParseRouterAPIInfo(fileName string, astFile *ast.File) error {
|
||||
for _, astDescription := range astFile.Decls {
|
||||
@@ -1365,7 +1361,7 @@ func replaceLastTag(slice []spec.Tag, element spec.Tag) {
|
||||
slice = append(slice[:len(slice)-1], element)
|
||||
}
|
||||
|
||||
// defineTypeOfExample example value define the type (object and array unsupported)
|
||||
// defineTypeOfExample example value define the type (object and array unsupported).
|
||||
func defineTypeOfExample(schemaType, arrayType, exampleValue string) (interface{}, error) {
|
||||
switch schemaType {
|
||||
case STRING:
|
||||
|
2
vendor/github.com/swaggo/swag/version.go
generated
vendored
2
vendor/github.com/swaggo/swag/version.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swag
|
||||
|
||||
// Version of swag.
|
||||
const Version = "v1.8.1"
|
||||
const Version = "v1.8.3"
|
||||
|
Reference in New Issue
Block a user