mirror of
https://github.com/coredns/coredns.git
synced 2025-11-03 10:43:20 -05:00
plugin/kubernetes: Enable protobuf, Update client api package (#1114)
* vendor * code
This commit is contained in:
committed by
John Belamaric
parent
45b0252c1a
commit
4b3a430ff2
4
vendor/github.com/emicklei/go-restful-swagger12/.travis.yml
generated
vendored
Normal file
4
vendor/github.com/emicklei/go-restful-swagger12/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
@@ -1,5 +1,8 @@
|
||||
Change history of swagger
|
||||
=
|
||||
2017-01-30
|
||||
- moved from go-restful/swagger to go-restful-swagger12
|
||||
|
||||
2015-10-16
|
||||
- add type override mechanism for swagger models (MR 254, nathanejohnson)
|
||||
- replace uses of wildcard in generated apidocs (issue 251)
|
||||
22
vendor/github.com/emicklei/go-restful-swagger12/LICENSE
generated
vendored
Normal file
22
vendor/github.com/emicklei/go-restful-swagger12/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2017 Ernest Micklei
|
||||
|
||||
MIT License
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
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.
|
||||
@@ -1,3 +1,8 @@
|
||||
# go-restful-swagger12
|
||||
|
||||
[](https://travis-ci.org/emicklei/go-restful-swagger12)
|
||||
[](https://godoc.org/github.com/emicklei/go-restful-swagger12)
|
||||
|
||||
How to use Swagger UI with go-restful
|
||||
=
|
||||
|
||||
@@ -74,3 +79,5 @@ Notes
|
||||
--
|
||||
- The Nickname of an Operation is automatically set by finding the name of the function. You can override it using RouteBuilder.Operation(..)
|
||||
- The WebServices field of swagger.Config can be used to control which service you want to expose and document ; you can have multiple configs and therefore multiple endpoints.
|
||||
|
||||
© 2017, ernestmicklei.com. MIT License. Contributions welcome.
|
||||
@@ -2,6 +2,7 @@ package swagger
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
@@ -9,6 +10,13 @@ import (
|
||||
// PostBuildDeclarationMapFunc can be used to modify the api declaration map.
|
||||
type PostBuildDeclarationMapFunc func(apiDeclarationMap *ApiDeclarationList)
|
||||
|
||||
// MapSchemaFormatFunc can be used to modify typeName at definition time.
|
||||
type MapSchemaFormatFunc func(typeName string) string
|
||||
|
||||
// MapModelTypeNameFunc can be used to return the desired typeName for a given
|
||||
// type. It will return false if the default name should be used.
|
||||
type MapModelTypeNameFunc func(t reflect.Type) (string, bool)
|
||||
|
||||
type Config struct {
|
||||
// url where the services are available, e.g. http://localhost:8080
|
||||
// if left empty then the basePath of Swagger is taken from the actual request
|
||||
@@ -31,4 +39,8 @@ type Config struct {
|
||||
PostBuildHandler PostBuildDeclarationMapFunc
|
||||
// Swagger global info struct
|
||||
Info Info
|
||||
// [optional] If set, model builder should call this handler to get addition typename-to-swagger-format-field conversion.
|
||||
SchemaFormatHandler MapSchemaFormatFunc
|
||||
// [optional] If set, model builder should call this handler to retrieve the name for a given type.
|
||||
ModelTypeNameHandler MapModelTypeNameFunc
|
||||
}
|
||||
@@ -14,6 +14,7 @@ type ModelBuildable interface {
|
||||
|
||||
type modelBuilder struct {
|
||||
Models *ModelList
|
||||
Config *Config
|
||||
}
|
||||
|
||||
type documentable interface {
|
||||
@@ -42,6 +43,12 @@ func (b modelBuilder) addModelFrom(sample interface{}) {
|
||||
}
|
||||
|
||||
func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
||||
// Turn pointers into simpler types so further checks are
|
||||
// correct.
|
||||
if st.Kind() == reflect.Ptr {
|
||||
st = st.Elem()
|
||||
}
|
||||
|
||||
modelName := b.keyFrom(st)
|
||||
if nameOverride != "" {
|
||||
modelName = nameOverride
|
||||
@@ -50,6 +57,14 @@ func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
||||
if b.isPrimitiveType(modelName) {
|
||||
return nil
|
||||
}
|
||||
// golang encoding/json packages says array and slice values encode as
|
||||
// JSON arrays, except that []byte encodes as a base64-encoded string.
|
||||
// If we see a []byte here, treat it at as a primitive type (string)
|
||||
// and deal with it in buildArrayTypeProperty.
|
||||
if (st.Kind() == reflect.Slice || st.Kind() == reflect.Array) &&
|
||||
st.Elem().Kind() == reflect.Uint8 {
|
||||
return nil
|
||||
}
|
||||
// see if we already have visited this model
|
||||
if _, ok := b.Models.At(modelName); ok {
|
||||
return nil
|
||||
@@ -128,6 +143,11 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if field.Name == "XMLName" && field.Type.String() == "xml.Name" {
|
||||
// property is metadata for the xml.Name attribute, can be skipped
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if tag := field.Tag.Get("modelDescription"); tag != "" {
|
||||
modelDescription = tag
|
||||
}
|
||||
@@ -146,7 +166,7 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
|
||||
prop.Type = &pType
|
||||
}
|
||||
if prop.Format == "" {
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String())
|
||||
prop.Format = b.jsonSchemaFormat(b.keyFrom(fieldType))
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
@@ -178,18 +198,19 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Map:
|
||||
// if it's a map, it's unstructured, and swagger 1.2 can't handle it
|
||||
anyt := "any"
|
||||
prop.Type = &anyt
|
||||
objectType := "object"
|
||||
prop.Type = &objectType
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
if b.isPrimitiveType(fieldType.String()) {
|
||||
mapped := b.jsonSchemaType(fieldType.String())
|
||||
fieldTypeName := b.keyFrom(fieldType)
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
mapped := b.jsonSchemaType(fieldTypeName)
|
||||
prop.Type = &mapped
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String())
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
modelType := fieldType.String()
|
||||
modelType := b.keyFrom(fieldType)
|
||||
prop.Ref = &modelType
|
||||
|
||||
if fieldType.Name() == "" { // override type of anonymous structs
|
||||
@@ -231,7 +252,7 @@ func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonNam
|
||||
|
||||
if field.Name == fieldType.Name() && field.Anonymous && !hasNamedJSONTag(field) {
|
||||
// embedded struct
|
||||
sub := modelBuilder{new(ModelList)}
|
||||
sub := modelBuilder{new(ModelList), b.Config}
|
||||
sub.addModel(fieldType, "")
|
||||
subKey := sub.keyFrom(fieldType)
|
||||
// merge properties from sub
|
||||
@@ -263,7 +284,7 @@ func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonNam
|
||||
}
|
||||
// simple struct
|
||||
b.addModel(fieldType, "")
|
||||
var pType = fieldType.String()
|
||||
var pType = b.keyFrom(fieldType)
|
||||
prop.Ref = &pType
|
||||
return jsonName, prop
|
||||
}
|
||||
@@ -275,11 +296,17 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
|
||||
return jsonName, prop
|
||||
}
|
||||
fieldType := field.Type
|
||||
if fieldType.Elem().Kind() == reflect.Uint8 {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, prop
|
||||
}
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Name())
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
|
||||
prop.Items = new(Item)
|
||||
if b.isPrimitiveType(elemTypeName) {
|
||||
if isPrimitive {
|
||||
mapped := b.jsonSchemaType(elemTypeName)
|
||||
prop.Items.Type = &mapped
|
||||
} else {
|
||||
@@ -289,7 +316,9 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
|
||||
if fieldType.Elem().Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
}
|
||||
b.addModel(fieldType.Elem(), elemTypeName)
|
||||
if !isPrimitive {
|
||||
b.addModel(fieldType.Elem(), elemTypeName)
|
||||
}
|
||||
return jsonName, prop
|
||||
}
|
||||
|
||||
@@ -305,16 +334,25 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
|
||||
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
isPrimitive := b.isPrimitiveType(fieldType.Elem().Elem().Name())
|
||||
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
|
||||
prop.Items = &Item{Ref: &elemName}
|
||||
// add|overwrite model for element type
|
||||
b.addModel(fieldType.Elem().Elem(), elemName)
|
||||
if isPrimitive {
|
||||
primName := b.jsonSchemaType(elemName)
|
||||
prop.Items = &Item{Ref: &primName}
|
||||
} else {
|
||||
prop.Items = &Item{Ref: &elemName}
|
||||
}
|
||||
if !isPrimitive {
|
||||
// add|overwrite model for element type
|
||||
b.addModel(fieldType.Elem().Elem(), elemName)
|
||||
}
|
||||
} else {
|
||||
// non-array, pointer type
|
||||
var pType = b.jsonSchemaType(fieldType.String()[1:]) // no star, include pkg path
|
||||
if b.isPrimitiveType(fieldType.String()[1:]) {
|
||||
fieldTypeName := b.keyFrom(fieldType.Elem())
|
||||
var pType = b.jsonSchemaType(fieldTypeName) // no star, include pkg path
|
||||
if b.isPrimitiveType(fieldTypeName) {
|
||||
prop.Type = &pType
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String()[1:])
|
||||
prop.Format = b.jsonSchemaFormat(fieldTypeName)
|
||||
return jsonName, prop
|
||||
}
|
||||
prop.Ref = &pType
|
||||
@@ -330,19 +368,21 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
|
||||
|
||||
func (b modelBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
|
||||
if t.Kind() == reflect.Ptr {
|
||||
return t.String()[1:]
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Name() == "" {
|
||||
return modelName + "." + jsonName
|
||||
}
|
||||
if b.isPrimitiveType(t.Name()) {
|
||||
return b.jsonSchemaType(t.Name())
|
||||
}
|
||||
return b.keyFrom(t)
|
||||
}
|
||||
|
||||
func (b modelBuilder) keyFrom(st reflect.Type) string {
|
||||
key := st.String()
|
||||
if b.Config != nil && b.Config.ModelTypeNameHandler != nil {
|
||||
if name, ok := b.Config.ModelTypeNameHandler(st); ok {
|
||||
key = name
|
||||
}
|
||||
}
|
||||
if len(st.Name()) == 0 { // unnamed type
|
||||
// Swagger UI has special meaning for [
|
||||
key = strings.Replace(key, "[]", "||", -1)
|
||||
@@ -352,6 +392,9 @@ func (b modelBuilder) keyFrom(st reflect.Type) string {
|
||||
|
||||
// see also https://golang.org/ref/spec#Numeric_types
|
||||
func (b modelBuilder) isPrimitiveType(modelName string) bool {
|
||||
if len(modelName) == 0 {
|
||||
return false
|
||||
}
|
||||
return strings.Contains("uint uint8 uint16 uint32 uint64 int int8 int16 int32 int64 float32 float64 bool string byte rune time.Time", modelName)
|
||||
}
|
||||
|
||||
@@ -399,6 +442,11 @@ func (b modelBuilder) jsonSchemaType(modelName string) string {
|
||||
}
|
||||
|
||||
func (b modelBuilder) jsonSchemaFormat(modelName string) string {
|
||||
if b.Config != nil && b.Config.SchemaFormatHandler != nil {
|
||||
if mapped := b.Config.SchemaFormatHandler(modelName); mapped != "" {
|
||||
return mapped
|
||||
}
|
||||
}
|
||||
schemaMap := map[string]string{
|
||||
"int": "int32",
|
||||
"int32": "int32",
|
||||
@@ -1,7 +1,9 @@
|
||||
package swagger
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -38,6 +40,59 @@ func TestRef_Issue190(t *testing.T) {
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestWithoutAdditionalFormat(t *testing.T) {
|
||||
type mytime struct {
|
||||
time.Time
|
||||
}
|
||||
type usemytime struct {
|
||||
t mytime
|
||||
}
|
||||
testJsonFromStruct(t, usemytime{}, `{
|
||||
"swagger.usemytime": {
|
||||
"id": "swagger.usemytime",
|
||||
"required": [
|
||||
"t"
|
||||
],
|
||||
"properties": {
|
||||
"t": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestWithAdditionalFormat(t *testing.T) {
|
||||
type mytime struct {
|
||||
time.Time
|
||||
}
|
||||
type usemytime struct {
|
||||
t mytime
|
||||
}
|
||||
testJsonFromStructWithConfig(t, usemytime{}, `{
|
||||
"swagger.usemytime": {
|
||||
"id": "swagger.usemytime",
|
||||
"required": [
|
||||
"t"
|
||||
],
|
||||
"properties": {
|
||||
"t": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`, &Config{
|
||||
SchemaFormatHandler: func(typeName string) string {
|
||||
switch typeName {
|
||||
case "swagger.mytime":
|
||||
return "date-time"
|
||||
}
|
||||
return ""
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// clear && go test -v -test.run TestCustomMarshaller_Issue96 ...swagger
|
||||
func TestCustomMarshaller_Issue96(t *testing.T) {
|
||||
type Vote struct {
|
||||
@@ -803,8 +858,8 @@ type Region struct {
|
||||
// clear && go test -v -test.run TestRegion_Issue113 ...swagger
|
||||
func TestRegion_Issue113(t *testing.T) {
|
||||
testJsonFromStruct(t, []Region{}, `{
|
||||
"integer": {
|
||||
"id": "integer",
|
||||
"||swagger.Region": {
|
||||
"id": "||swagger.Region",
|
||||
"properties": {}
|
||||
},
|
||||
"swagger.Region": {
|
||||
@@ -816,10 +871,7 @@ func TestRegion_Issue113(t *testing.T) {
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "integer"
|
||||
}
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@@ -828,10 +880,6 @@ func TestRegion_Issue113(t *testing.T) {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"||swagger.Region": {
|
||||
"id": "||swagger.Region",
|
||||
"properties": {}
|
||||
}
|
||||
}`)
|
||||
}
|
||||
@@ -874,6 +922,25 @@ func TestIssue158(t *testing.T) {
|
||||
testJsonFromStruct(t, Customer{}, expected)
|
||||
}
|
||||
|
||||
func TestPointers(t *testing.T) {
|
||||
type Vote struct {
|
||||
What YesNo
|
||||
}
|
||||
testJsonFromStruct(t, &Vote{}, `{
|
||||
"swagger.Vote": {
|
||||
"id": "swagger.Vote",
|
||||
"required": [
|
||||
"What"
|
||||
],
|
||||
"properties": {
|
||||
"What": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestSlices(t *testing.T) {
|
||||
type Address struct {
|
||||
Country string `json:"country,omitempty"`
|
||||
@@ -1140,3 +1207,77 @@ func TestOverridenTypeTagE1(t *testing.T) {
|
||||
`
|
||||
testJsonFromStruct(t, E{}, expected)
|
||||
}
|
||||
|
||||
type XmlNamed struct {
|
||||
XMLName xml.Name `xml:"user"`
|
||||
Id string `json:"id" xml:"id"`
|
||||
Name string `json:"name" xml:"name"`
|
||||
}
|
||||
|
||||
func TestXmlNameStructs(t *testing.T) {
|
||||
expected := `
|
||||
{
|
||||
"swagger.XmlNamed": {
|
||||
"id": "swagger.XmlNamed",
|
||||
"required": [
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
testJsonFromStruct(t, XmlNamed{}, expected)
|
||||
}
|
||||
|
||||
func TestNameCustomization(t *testing.T) {
|
||||
expected := `
|
||||
{
|
||||
"swagger.A": {
|
||||
"id": "swagger.A",
|
||||
"description": "A struct",
|
||||
"required": [
|
||||
"SB"
|
||||
],
|
||||
"properties": {
|
||||
"SB": {
|
||||
"type": "string",
|
||||
"description": "SB field"
|
||||
},
|
||||
"metadata": {
|
||||
"$ref": "new.swagger.SpecialC1",
|
||||
"description": "C1 field"
|
||||
}
|
||||
}
|
||||
},
|
||||
"new.swagger.SpecialC1": {
|
||||
"id": "new.swagger.SpecialC1",
|
||||
"description": "C1 struct",
|
||||
"required": [
|
||||
"SC"
|
||||
],
|
||||
"properties": {
|
||||
"SC": {
|
||||
"type": "string",
|
||||
"description": "SC field"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
testJsonFromStructWithConfig(t, A{}, expected, &Config{
|
||||
ModelTypeNameHandler: func(t reflect.Type) (string, bool) {
|
||||
if t == reflect.TypeOf(C1{}) {
|
||||
return "new.swagger.SpecialC1", true
|
||||
}
|
||||
return "", false
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -33,6 +33,21 @@ func (prop *ModelProperty) setMaximum(field reflect.StructField) {
|
||||
|
||||
func (prop *ModelProperty) setType(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("type"); tag != "" {
|
||||
// Check if the first two characters of the type tag are
|
||||
// intended to emulate slice/array behaviour.
|
||||
//
|
||||
// If type is intended to be a slice/array then add the
|
||||
// overriden type to the array item instead of the main property
|
||||
if len(tag) > 2 && tag[0:2] == "[]" {
|
||||
pType := "array"
|
||||
prop.Type = &pType
|
||||
prop.Items = new(Item)
|
||||
|
||||
iType := tag[2:]
|
||||
prop.Items.Type = &iType
|
||||
return
|
||||
}
|
||||
|
||||
prop.Type = &tag
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,16 @@ import (
|
||||
// clear && go test -v -test.run TestThatExtraTagsAreReadIntoModel ...swagger
|
||||
func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
|
||||
type fakeint int
|
||||
type fakearray string
|
||||
type Anything struct {
|
||||
Name string `description:"name" modelDescription:"a test"`
|
||||
Size int `minimum:"0" maximum:"10"`
|
||||
Stati string `enum:"off|on" default:"on" modelDescription:"more description"`
|
||||
ID string `unique:"true"`
|
||||
FakeInt fakeint `type:"integer"`
|
||||
IP net.IP `type:"string"`
|
||||
Password string
|
||||
Name string `description:"name" modelDescription:"a test"`
|
||||
Size int `minimum:"0" maximum:"10"`
|
||||
Stati string `enum:"off|on" default:"on" modelDescription:"more description"`
|
||||
ID string `unique:"true"`
|
||||
FakeInt fakeint `type:"integer"`
|
||||
FakeArray fakearray `type:"[]string"`
|
||||
IP net.IP `type:"string"`
|
||||
Password string
|
||||
}
|
||||
m := modelsFromStruct(Anything{})
|
||||
props, _ := m.At("swagger.Anything")
|
||||
@@ -49,8 +51,16 @@ func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
|
||||
if got, want := *p6.Type, "integer"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p7, _ := props.Properties.At("IP")
|
||||
if got, want := *p7.Type, "string"; got != want {
|
||||
p7, _ := props.Properties.At("FakeArray")
|
||||
if got, want := *p7.Type, "array"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p7p, _ := props.Properties.At("FakeArray")
|
||||
if got, want := *p7p.Items.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p8, _ := props.Properties.At("IP")
|
||||
if got, want := *p8.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ type ApiDeclaration struct {
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
BasePath string `json:"basePath"`
|
||||
ResourcePath string `json:"resourcePath"` // must start with /
|
||||
Info Info `json:"info"`
|
||||
Apis []Api `json:"apis,omitempty"`
|
||||
Models ModelList `json:"models,omitempty"`
|
||||
Produces []string `json:"produces,omitempty"`
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful/swagger/test_package"
|
||||
"github.com/emicklei/go-restful-swagger12/test_package"
|
||||
)
|
||||
|
||||
func TestInfoStruct_Issue231(t *testing.T) {
|
||||
@@ -157,6 +157,53 @@ func TestWriteSamples(t *testing.T) {
|
||||
}`)
|
||||
}
|
||||
|
||||
func TestRoutesWithCommonPart(t *testing.T) {
|
||||
ws1 := new(restful.WebService)
|
||||
ws1.Path("/")
|
||||
ws1.Route(ws1.GET("/foobar").To(dummy).Writes(test_package.TestStruct{}))
|
||||
ws1.Route(ws1.HEAD("/foobar").To(dummy).Writes(test_package.TestStruct{}))
|
||||
ws1.Route(ws1.GET("/foo").To(dummy).Writes([]test_package.TestStruct{}))
|
||||
ws1.Route(ws1.HEAD("/foo").To(dummy).Writes(test_package.TestStruct{}))
|
||||
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws1},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
|
||||
decl := sws.composeDeclaration(ws1, "/foo")
|
||||
|
||||
str, err := json.MarshalIndent(decl.Apis, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
compareJson(t, string(str), `[
|
||||
{
|
||||
"path": "/foo",
|
||||
"description": "",
|
||||
"operations": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "test_package.TestStruct"
|
||||
},
|
||||
"method": "GET",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
},
|
||||
{
|
||||
"type": "test_package.TestStruct",
|
||||
"method": "HEAD",
|
||||
"nickname": "dummy",
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]`)
|
||||
}
|
||||
|
||||
// go test -v -test.run TestServiceToApi ...swagger
|
||||
func TestServiceToApi(t *testing.T) {
|
||||
ws := new(restful.WebService)
|
||||
@@ -226,25 +273,12 @@ func TestComposeResponseMessages(t *testing.T) {
|
||||
route := restful.Route{ResponseErrors: responseErrors}
|
||||
decl := new(ApiDeclaration)
|
||||
decl.Models = ModelList{}
|
||||
msgs := composeResponseMessages(route, decl)
|
||||
msgs := composeResponseMessages(route, decl, &Config{})
|
||||
if msgs[0].ResponseModel != "swagger.TestItem" {
|
||||
t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel)
|
||||
}
|
||||
}
|
||||
|
||||
// clear && go test -v -test.run TestComposeResponseMessageArray ...swagger
|
||||
func TestComposeResponseMessageArray(t *testing.T) {
|
||||
responseErrors := map[int]restful.ResponseError{}
|
||||
responseErrors[400] = restful.ResponseError{Code: 400, Message: "Bad Request", Model: []TestItem{}}
|
||||
route := restful.Route{ResponseErrors: responseErrors}
|
||||
decl := new(ApiDeclaration)
|
||||
decl.Models = ModelList{}
|
||||
msgs := composeResponseMessages(route, decl)
|
||||
if msgs[0].ResponseModel != "array[swagger.TestItem]" {
|
||||
t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue78(t *testing.T) {
|
||||
sws := newSwaggerService(Config{})
|
||||
models := new(ModelList)
|
||||
@@ -226,6 +226,9 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
|
||||
pathToRoutes := newOrderedRouteMap()
|
||||
for _, other := range ws.Routes() {
|
||||
if strings.HasPrefix(other.Path, pathPrefix) {
|
||||
if len(pathPrefix) > 1 && len(other.Path) > len(pathPrefix) && other.Path[len(pathPrefix)] != '/' {
|
||||
continue
|
||||
}
|
||||
pathToRoutes.Add(other.Path, other)
|
||||
}
|
||||
}
|
||||
@@ -241,7 +244,7 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
|
||||
DataTypeFields: DataTypeFields{Type: &voidString},
|
||||
Parameters: []Parameter{},
|
||||
Nickname: route.Operation,
|
||||
ResponseMessages: composeResponseMessages(route, &decl)}
|
||||
ResponseMessages: composeResponseMessages(route, &decl, &sws.config)}
|
||||
|
||||
operation.Consumes = route.Consumes
|
||||
operation.Produces = route.Produces
|
||||
@@ -271,13 +274,13 @@ func withoutWildcard(path string) string {
|
||||
}
|
||||
|
||||
// composeResponseMessages takes the ResponseErrors (if any) and creates ResponseMessages from them.
|
||||
func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (messages []ResponseMessage) {
|
||||
func composeResponseMessages(route restful.Route, decl *ApiDeclaration, config *Config) (messages []ResponseMessage) {
|
||||
if route.ResponseErrors == nil {
|
||||
return messages
|
||||
}
|
||||
// sort by code
|
||||
codes := sort.IntSlice{}
|
||||
for code, _ := range route.ResponseErrors {
|
||||
for code := range route.ResponseErrors {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
codes.Sort()
|
||||
@@ -290,13 +293,12 @@ func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (message
|
||||
if each.Model != nil {
|
||||
st := reflect.TypeOf(each.Model)
|
||||
isCollection, st := detectCollectionType(st)
|
||||
modelName := modelBuilder{}.keyFrom(st)
|
||||
if isCollection {
|
||||
modelName = "array[" + modelName + "]"
|
||||
// collection cannot be in responsemodel
|
||||
if !isCollection {
|
||||
modelName := modelBuilder{}.keyFrom(st)
|
||||
modelBuilder{Models: &decl.Models, Config: config}.addModel(st, "")
|
||||
message.ResponseModel = modelName
|
||||
}
|
||||
modelBuilder{&decl.Models}.addModel(st, "")
|
||||
// reference the model
|
||||
message.ResponseModel = modelName
|
||||
}
|
||||
messages = append(messages, message)
|
||||
}
|
||||
@@ -331,12 +333,13 @@ func detectCollectionType(st reflect.Type) (bool, reflect.Type) {
|
||||
|
||||
// addModelFromSample creates and adds (or overwrites) a Model from a sample resource
|
||||
func (sws SwaggerService) addModelFromSampleTo(operation *Operation, isResponse bool, sample interface{}, models *ModelList) {
|
||||
mb := modelBuilder{Models: models, Config: &sws.config}
|
||||
if isResponse {
|
||||
type_, items := asDataType(sample)
|
||||
operation.Type = type_
|
||||
sampleType, items := asDataType(sample, &sws.config)
|
||||
operation.Type = sampleType
|
||||
operation.Items = items
|
||||
}
|
||||
modelBuilder{models}.addModelFrom(sample)
|
||||
mb.addModelFrom(sample)
|
||||
}
|
||||
|
||||
func asSwaggerParameter(param restful.ParameterData) Parameter {
|
||||
@@ -411,7 +414,7 @@ func asParamType(kind int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func asDataType(any interface{}) (*string, *Item) {
|
||||
func asDataType(any interface{}, config *Config) (*string, *Item) {
|
||||
// If it's not a collection, return the suggested model name
|
||||
st := reflect.TypeOf(any)
|
||||
isCollection, st := detectCollectionType(st)
|
||||
@@ -424,7 +427,7 @@ func asDataType(any interface{}) (*string, *Item) {
|
||||
// XXX: This is not very elegant
|
||||
// We create an Item object referring to the given model
|
||||
models := ModelList{}
|
||||
mb := modelBuilder{&models}
|
||||
mb := modelBuilder{Models: &models, Config: config}
|
||||
mb.addModelFrom(any)
|
||||
|
||||
elemTypeName := mb.getElementTypeName(modelName, "", st)
|
||||
@@ -9,19 +9,27 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool {
|
||||
m := modelsFromStruct(sample)
|
||||
func testJsonFromStructWithConfig(t *testing.T, sample interface{}, expectedJson string, config *Config) bool {
|
||||
m := modelsFromStructWithConfig(sample, config)
|
||||
data, _ := json.MarshalIndent(m, " ", " ")
|
||||
return compareJson(t, string(data), expectedJson)
|
||||
}
|
||||
|
||||
func modelsFromStruct(sample interface{}) *ModelList {
|
||||
func modelsFromStructWithConfig(sample interface{}, config *Config) *ModelList {
|
||||
models := new(ModelList)
|
||||
builder := modelBuilder{models}
|
||||
builder := modelBuilder{Models: models, Config: config}
|
||||
builder.addModelFrom(sample)
|
||||
return models
|
||||
}
|
||||
|
||||
func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool {
|
||||
return testJsonFromStructWithConfig(t, sample, expectedJson, &Config{})
|
||||
}
|
||||
|
||||
func modelsFromStruct(sample interface{}) *ModelList {
|
||||
return modelsFromStructWithConfig(sample, &Config{})
|
||||
}
|
||||
|
||||
func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString string) bool {
|
||||
success := false
|
||||
var actualMap map[string]interface{}
|
||||
@@ -35,7 +43,7 @@ func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString s
|
||||
err := json.Unmarshal([]byte(expectedJsonAsString), &expectedArray)
|
||||
success = reflect.DeepEqual(actualArray, expectedArray)
|
||||
if err != nil {
|
||||
t.Fatalf("Unparsable expected JSON: %s", err)
|
||||
t.Fatalf("Unparsable expected JSON: %s, actual: %v, expected: %v", err, actualJsonAsString, expectedJsonAsString)
|
||||
}
|
||||
} else {
|
||||
success = reflect.DeepEqual(actualMap, expectedMap)
|
||||
Reference in New Issue
Block a user