mirror of https://github.com/k3s-io/k3s
commit
e706e8138b
|
@ -199,8 +199,8 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/emicklei/go-restful",
|
||||
"Comment": "v1.1.3-54-gbdfb7d4",
|
||||
"Rev": "bdfb7d41639a84ea7c36df648e5865cd9fbf21e2"
|
||||
"Comment": "v1.1.3-76-gbfd6ff2",
|
||||
"Rev": "bfd6ff29d2961031cec64346a92bae4cde96c868"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/evanphx/json-patch",
|
||||
|
|
|
@ -150,11 +150,20 @@ func writeServiceError(err ServiceError, req *Request, resp *Response) {
|
|||
|
||||
// Dispatch the incoming Http Request to a matching WebService.
|
||||
func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.Request) {
|
||||
writer := httpWriter
|
||||
|
||||
// CompressingResponseWriter should be closed after all operations are done
|
||||
defer func() {
|
||||
if compressWriter, ok := writer.(*CompressingResponseWriter); ok {
|
||||
compressWriter.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// Instal panic recovery unless told otherwise
|
||||
if !c.doNotRecover { // catch all for 500 response
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
c.recoverHandleFunc(r, httpWriter)
|
||||
c.recoverHandleFunc(r, writer)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
@ -168,7 +177,6 @@ func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.R
|
|||
|
||||
// Detect if compression is needed
|
||||
// assume without compression, test for override
|
||||
writer := httpWriter
|
||||
if c.contentEncodingEnabled {
|
||||
doCompress, encoding := wantsCompressedResponse(httpRequest)
|
||||
if doCompress {
|
||||
|
@ -179,9 +187,6 @@ func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.R
|
|||
httpWriter.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
writer.(*CompressingResponseWriter).Close()
|
||||
}()
|
||||
}
|
||||
}
|
||||
// Find best match Route ; err is non nil if no match was found
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
cd examples
|
||||
ls *.go | xargs -I {} go build {}
|
||||
ls *.go | xargs -I {} go build -o /tmp/ignore {}
|
||||
cd ..
|
||||
go fmt ...swagger && \
|
||||
go test -test.v ...swagger && \
|
||||
|
|
|
@ -209,9 +209,10 @@ func (r *Response) WriteErrorString(status int, errorReason string) error {
|
|||
// 204 (http.StatusNoContent) or 304 (http.StatusNotModified))
|
||||
func (r *Response) WriteHeader(httpStatus int) {
|
||||
r.statusCode = httpStatus
|
||||
// if 204 then WriteEntity will not be called so we need to pass this code
|
||||
// if 201,204,304 then WriteEntity will not be called so we need to pass this code
|
||||
if http.StatusNoContent == httpStatus ||
|
||||
http.StatusNotModified == httpStatus {
|
||||
http.StatusNotModified == httpStatus ||
|
||||
http.StatusPartialContent == httpStatus {
|
||||
r.ResponseWriter.WriteHeader(httpStatus)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,25 @@ func TestMeasureContentLengthWriteErrorString(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// go test -v -test.run TestStatusIsPassedToResponse ...restful
|
||||
func TestStatusIsPassedToResponse(t *testing.T) {
|
||||
for _, each := range []struct {
|
||||
write, read int
|
||||
}{
|
||||
{write: 204, read: 204},
|
||||
{write: 304, read: 304},
|
||||
{write: 200, read: 200},
|
||||
{write: 400, read: 200},
|
||||
} {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true}
|
||||
resp.WriteHeader(each.write)
|
||||
if got, want := httpWriter.Code, each.read; got != want {
|
||||
t.Error("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// go test -v -test.run TestStatusCreatedAndContentTypeJson_Issue54 ...restful
|
||||
func TestStatusCreatedAndContentTypeJson_Issue54(t *testing.T) {
|
||||
httpWriter := httptest.NewRecorder()
|
||||
|
|
|
@ -21,8 +21,56 @@ Now, you can install the Swagger WebService for serving the Swagger specificatio
|
|||
swagger.InstallSwaggerService(config)
|
||||
|
||||
|
||||
Documenting Structs
|
||||
--
|
||||
|
||||
Currently there are 2 ways to document your structs in the go-restful Swagger.
|
||||
|
||||
###### By using struct tags
|
||||
- Use tag "description" to annotate a struct field with a description to show in the UI
|
||||
- Use tag "modelDescription" to annotate the struct itself with a description to show in the UI. The tag can be added in an field of the struct and in case that there are multiple definition, they will be appended with an empty line.
|
||||
|
||||
###### By using the SwaggerDoc method
|
||||
Here is an example with an `Address` struct and the documentation for each of the fields. The `""` is a special entry for **documenting the struct itself**.
|
||||
|
||||
type Address struct {
|
||||
Country string `json:"country,omitempty"`
|
||||
PostCode int `json:"postcode,omitempty"`
|
||||
}
|
||||
|
||||
func (Address) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "Address doc",
|
||||
"country": "Country doc",
|
||||
"postcode": "PostCode doc",
|
||||
}
|
||||
}
|
||||
|
||||
This example will generate a JSON like this
|
||||
|
||||
{
|
||||
"Address": {
|
||||
"id": "Address",
|
||||
"description": "Address doc",
|
||||
"properties": {
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Country doc"
|
||||
},
|
||||
"postcode": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "PostCode doc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
**Very Important Notes:**
|
||||
- `SwaggerDoc()` is using a **NON-Pointer** receiver (e.g. func (Address) and not func (*Address))
|
||||
- The returned map should use as key the name of the field as defined in the JSON parameter (e.g. `"postcode"` and not `"PostCode"`)
|
||||
|
||||
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.
|
||||
- Use tag "description" to annotate a struct field with a description to show in the UI
|
|
@ -16,6 +16,19 @@ type modelBuilder struct {
|
|||
Models *ModelList
|
||||
}
|
||||
|
||||
type documentable interface {
|
||||
SwaggerDoc() map[string]string
|
||||
}
|
||||
|
||||
// Check if this structure has a method with signature func (<theModel>) SwaggerDoc() map[string]string
|
||||
// If it exists, retrive the documentation and overwrite all struct tag descriptions
|
||||
func getDocFromMethodSwaggerDoc2(model reflect.Type) map[string]string {
|
||||
if docable, ok := reflect.New(model).Elem().Interface().(documentable); ok {
|
||||
return docable.SwaggerDoc()
|
||||
}
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
// addModelFrom creates and adds a Model to the builder and detects and calls
|
||||
// the post build hook for customizations
|
||||
func (b modelBuilder) addModelFrom(sample interface{}) {
|
||||
|
@ -58,14 +71,23 @@ func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
|||
if st.Kind() != reflect.Struct {
|
||||
return &sm
|
||||
}
|
||||
|
||||
fullDoc := getDocFromMethodSwaggerDoc2(st)
|
||||
modelDescriptions := []string{}
|
||||
|
||||
for i := 0; i < st.NumField(); i++ {
|
||||
field := st.Field(i)
|
||||
jsonName, prop := b.buildProperty(field, &sm, modelName)
|
||||
if descTag := field.Tag.Get("description"); descTag != "" {
|
||||
prop.Description = descTag
|
||||
jsonName, modelDescription, prop := b.buildProperty(field, &sm, modelName)
|
||||
if len(modelDescription) > 0 {
|
||||
modelDescriptions = append(modelDescriptions, modelDescription)
|
||||
}
|
||||
// add if not ommitted
|
||||
|
||||
// add if not omitted
|
||||
if len(jsonName) != 0 {
|
||||
// update description
|
||||
if fieldDoc, ok := fullDoc[jsonName]; ok {
|
||||
prop.Description = fieldDoc
|
||||
}
|
||||
// update Required
|
||||
if b.isPropertyRequired(field) {
|
||||
sm.Required = append(sm.Required, jsonName)
|
||||
|
@ -73,6 +95,15 @@ func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
|
|||
sm.Properties.Put(jsonName, prop)
|
||||
}
|
||||
}
|
||||
|
||||
// We always overwrite documentation if SwaggerDoc method exists
|
||||
// "" is special for documenting the struct itself
|
||||
if modelDoc, ok := fullDoc[""]; ok {
|
||||
sm.Description = modelDoc
|
||||
} else if len(modelDescriptions) != 0 {
|
||||
sm.Description = strings.Join(modelDescriptions, "\n")
|
||||
}
|
||||
|
||||
// update model builder with completed model
|
||||
b.Models.Put(modelName, sm)
|
||||
|
||||
|
@ -90,21 +121,32 @@ func (b modelBuilder) isPropertyRequired(field reflect.StructField) bool {
|
|||
return required
|
||||
}
|
||||
|
||||
func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, modelName string) (jsonName string, prop ModelProperty) {
|
||||
func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, modelName string) (jsonName, modelDescription string, prop ModelProperty) {
|
||||
jsonName = b.jsonNameOfField(field)
|
||||
if len(jsonName) == 0 {
|
||||
// empty name signals skip property
|
||||
return "", prop
|
||||
return "", "", prop
|
||||
}
|
||||
|
||||
if tag := field.Tag.Get("modelDescription"); tag != "" {
|
||||
modelDescription = tag
|
||||
}
|
||||
|
||||
fieldType := field.Type
|
||||
|
||||
prop.setPropertyMetadata(field)
|
||||
|
||||
// check if type is doing its own marshalling
|
||||
marshalerType := reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
if fieldType.Implements(marshalerType) {
|
||||
var pType = "string"
|
||||
prop.Type = &pType
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String())
|
||||
return jsonName, prop
|
||||
if prop.Type == nil {
|
||||
prop.Type = &pType
|
||||
}
|
||||
if prop.Format == "" {
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String())
|
||||
}
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
// check if annotation says it is a string
|
||||
|
@ -113,34 +155,37 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
|
|||
if len(s) > 1 && s[1] == "string" {
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, prop
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
}
|
||||
|
||||
fieldKind := fieldType.Kind()
|
||||
switch {
|
||||
case fieldKind == reflect.Struct:
|
||||
return b.buildStructTypeProperty(field, jsonName, model)
|
||||
jsonName, prop := b.buildStructTypeProperty(field, jsonName, model)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Slice || fieldKind == reflect.Array:
|
||||
return b.buildArrayTypeProperty(field, jsonName, modelName)
|
||||
jsonName, prop := b.buildArrayTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.Ptr:
|
||||
return b.buildPointerTypeProperty(field, jsonName, modelName)
|
||||
jsonName, prop := b.buildPointerTypeProperty(field, jsonName, modelName)
|
||||
return jsonName, modelDescription, prop
|
||||
case fieldKind == reflect.String:
|
||||
stringt := "string"
|
||||
prop.Type = &stringt
|
||||
return jsonName, prop
|
||||
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
|
||||
return jsonName, prop
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
if b.isPrimitiveType(fieldType.String()) {
|
||||
mapped := b.jsonSchemaType(fieldType.String())
|
||||
prop.Type = &mapped
|
||||
prop.Format = b.jsonSchemaFormat(fieldType.String())
|
||||
return jsonName, prop
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
modelType := fieldType.String()
|
||||
prop.Ref = &modelType
|
||||
|
@ -150,7 +195,7 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
|
|||
prop.Ref = &nestedTypeName
|
||||
b.addModel(fieldType, nestedTypeName)
|
||||
}
|
||||
return jsonName, prop
|
||||
return jsonName, modelDescription, prop
|
||||
}
|
||||
|
||||
func hasNamedJSONTag(field reflect.StructField) bool {
|
||||
|
@ -168,6 +213,7 @@ func hasNamedJSONTag(field reflect.StructField) bool {
|
|||
|
||||
func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonName string, model *Model) (nameJson string, prop ModelProperty) {
|
||||
fieldType := field.Type
|
||||
prop.setPropertyMetadata(field)
|
||||
// check for anonymous
|
||||
if len(fieldType.Name()) == 0 {
|
||||
// anonymous
|
||||
|
@ -218,6 +264,7 @@ func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonNam
|
|||
|
||||
func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
fieldType := field.Type
|
||||
prop.setPropertyMetadata(field)
|
||||
var pType = "array"
|
||||
prop.Type = &pType
|
||||
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
|
||||
|
@ -238,6 +285,7 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
|
|||
|
||||
func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonName, modelName string) (nameJson string, prop ModelProperty) {
|
||||
fieldType := field.Type
|
||||
prop.setPropertyMetadata(field)
|
||||
|
||||
// override type of pointer to list-likes
|
||||
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
|
||||
|
|
131
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_builder_test.go
generated
vendored
131
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_builder_test.go
generated
vendored
|
@ -978,3 +978,134 @@ func TestEmbeddedStructPull204(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
}
|
||||
|
||||
type AddressWithMethod struct {
|
||||
Country string `json:"country,omitempty"`
|
||||
PostCode int `json:"postcode,omitempty"`
|
||||
}
|
||||
|
||||
func (AddressWithMethod) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "Address doc",
|
||||
"country": "Country doc",
|
||||
"postcode": "PostCode doc",
|
||||
}
|
||||
}
|
||||
|
||||
func TestDocInMethodSwaggerDoc(t *testing.T) {
|
||||
expected := `{
|
||||
"swagger.AddressWithMethod": {
|
||||
"id": "swagger.AddressWithMethod",
|
||||
"description": "Address doc",
|
||||
"properties": {
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Country doc"
|
||||
},
|
||||
"postcode": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "PostCode doc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
testJsonFromStruct(t, AddressWithMethod{}, expected)
|
||||
}
|
||||
|
||||
type RefDesc struct {
|
||||
f1 *int64 `description:"desc"`
|
||||
}
|
||||
|
||||
func TestPtrDescription(t *testing.T) {
|
||||
b := RefDesc{}
|
||||
expected := `{
|
||||
"swagger.RefDesc": {
|
||||
"id": "swagger.RefDesc",
|
||||
"required": [
|
||||
"f1"
|
||||
],
|
||||
"properties": {
|
||||
"f1": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "desc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
testJsonFromStruct(t, b, expected)
|
||||
}
|
||||
|
||||
type A struct {
|
||||
B `json:",inline"`
|
||||
C1 `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type B struct {
|
||||
SB string
|
||||
}
|
||||
|
||||
type C1 struct {
|
||||
SC string
|
||||
}
|
||||
|
||||
func (A) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "A struct",
|
||||
"B": "B field", // We should not get anything from this
|
||||
"metadata": "C1 field",
|
||||
}
|
||||
}
|
||||
|
||||
func (B) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "B struct",
|
||||
"SB": "SB field",
|
||||
}
|
||||
}
|
||||
|
||||
func (C1) SwaggerDoc() map[string]string {
|
||||
return map[string]string{
|
||||
"": "C1 struct",
|
||||
"SC": "SC field",
|
||||
}
|
||||
}
|
||||
|
||||
func TestNestedStructDescription(t *testing.T) {
|
||||
expected := `
|
||||
{
|
||||
"swagger.A": {
|
||||
"id": "swagger.A",
|
||||
"description": "A struct",
|
||||
"required": [
|
||||
"SB"
|
||||
],
|
||||
"properties": {
|
||||
"SB": {
|
||||
"type": "string",
|
||||
"description": "SB field"
|
||||
},
|
||||
"metadata": {
|
||||
"$ref": "swagger.C1",
|
||||
"description": "C1 field"
|
||||
}
|
||||
}
|
||||
},
|
||||
"swagger.C1": {
|
||||
"id": "swagger.C1",
|
||||
"description": "C1 struct",
|
||||
"required": [
|
||||
"SC"
|
||||
],
|
||||
"properties": {
|
||||
"SC": {
|
||||
"type": "string",
|
||||
"description": "SC field"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
testJsonFromStruct(t, A{}, expected)
|
||||
}
|
||||
|
|
59
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext.go
generated
vendored
Normal file
59
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
package swagger
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (prop *ModelProperty) setDescription(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("description"); tag != "" {
|
||||
prop.Description = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setDefaultValue(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("default"); tag != "" {
|
||||
prop.DefaultValue = Special(tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setEnumValues(field reflect.StructField) {
|
||||
// We use | to separate the enum values. This value is chosen
|
||||
// since its unlikely to be useful in actual enumeration values.
|
||||
if tag := field.Tag.Get("enum"); tag != "" {
|
||||
prop.Enum = strings.Split(tag, "|")
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setMaximum(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("maximum"); tag != "" {
|
||||
prop.Maximum = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setMinimum(field reflect.StructField) {
|
||||
if tag := field.Tag.Get("minimum"); tag != "" {
|
||||
prop.Minimum = tag
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setUniqueItems(field reflect.StructField) {
|
||||
tag := field.Tag.Get("unique")
|
||||
switch tag {
|
||||
case "true":
|
||||
v := true
|
||||
prop.UniqueItems = &v
|
||||
case "false":
|
||||
v := false
|
||||
prop.UniqueItems = &v
|
||||
}
|
||||
}
|
||||
|
||||
func (prop *ModelProperty) setPropertyMetadata(field reflect.StructField) {
|
||||
prop.setDescription(field)
|
||||
prop.setEnumValues(field)
|
||||
prop.setMinimum(field)
|
||||
prop.setMaximum(field)
|
||||
prop.setUniqueItems(field)
|
||||
prop.setDefaultValue(field)
|
||||
}
|
46
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext_test.go
generated
vendored
Normal file
46
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext_test.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package swagger
|
||||
|
||||
import "testing"
|
||||
|
||||
// clear && go test -v -test.run TestThatExtraTagsAreReadIntoModel ...swagger
|
||||
func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
|
||||
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"`
|
||||
Password string
|
||||
}
|
||||
m := modelsFromStruct(Anything{})
|
||||
props, _ := m.At("swagger.Anything")
|
||||
p1, _ := props.Properties.At("Name")
|
||||
if got, want := p1.Description, "name"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p2, _ := props.Properties.At("Size")
|
||||
if got, want := p2.Minimum, "0"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
if got, want := p2.Maximum, "10"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p3, _ := props.Properties.At("Stati")
|
||||
if got, want := p3.Enum[0], "off"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
if got, want := p3.Enum[1], "on"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p4, _ := props.Properties.At("ID")
|
||||
if got, want := *p4.UniqueItems, true; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
p5, _ := props.Properties.At("Password")
|
||||
if got, want := *p5.Type, "string"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := props.Description, "a test\nmore description"; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
|
@ -6,6 +6,24 @@ import (
|
|||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
||||
// go test -v -test.run TestThatMultiplePathsOnRootAreHandled ...swagger
|
||||
func TestThatMultiplePathsOnRootAreHandled(t *testing.T) {
|
||||
ws1 := new(restful.WebService)
|
||||
ws1.Route(ws1.GET("/_ping").To(dummy))
|
||||
ws1.Route(ws1.GET("/version").To(dummy))
|
||||
|
||||
cfg := Config{
|
||||
WebServicesUrl: "http://here.com",
|
||||
ApiPath: "/apipath",
|
||||
WebServices: []*restful.WebService{ws1},
|
||||
}
|
||||
sws := newSwaggerService(cfg)
|
||||
decl := sws.composeDeclaration(ws1, "/")
|
||||
if got, want := len(decl.Apis), 2; got != want {
|
||||
t.Errorf("got %v want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// go test -v -test.run TestServiceToApi ...swagger
|
||||
func TestServiceToApi(t *testing.T) {
|
||||
ws := new(restful.WebService)
|
||||
|
|
3
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_webservice.go
generated
vendored
3
Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_webservice.go
generated
vendored
|
@ -178,11 +178,12 @@ func (sws SwaggerService) getDeclarations(req *restful.Request, resp *restful.Re
|
|||
resp.WriteAsJson(decl)
|
||||
}
|
||||
|
||||
// composeDeclaration uses all routes and parameters to create a ApiDeclaration
|
||||
func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix string) ApiDeclaration {
|
||||
decl := ApiDeclaration{
|
||||
SwaggerVersion: swaggerVersion,
|
||||
BasePath: sws.config.WebServicesUrl,
|
||||
ResourcePath: ws.RootPath(),
|
||||
ResourcePath: pathPrefix,
|
||||
Models: ModelList{},
|
||||
ApiVersion: ws.Version()}
|
||||
|
||||
|
|
|
@ -50,6 +50,20 @@ func TestCapturePanic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCapturePanicWithEncoded(t *testing.T) {
|
||||
tearDown()
|
||||
Add(newPanicingService())
|
||||
DefaultContainer.EnableContentEncoding(true)
|
||||
httpRequest, _ := http.NewRequest("GET", "http://here.com/fire", nil)
|
||||
httpRequest.Header.Set("Accept", "*/*")
|
||||
httpRequest.Header.Set("Accept-Encoding", "gzip")
|
||||
httpWriter := httptest.NewRecorder()
|
||||
DefaultContainer.dispatch(httpWriter, httpRequest)
|
||||
if 500 != httpWriter.Code {
|
||||
t.Error("500 expected on fire, got", httpWriter.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNotFound(t *testing.T) {
|
||||
tearDown()
|
||||
httpRequest, _ := http.NewRequest("GET", "http://here.com/missing", nil)
|
||||
|
|
Loading…
Reference in New Issue