diff --git a/api_documentation/api_documentation.go b/api_documentation/api_documentation.go index 2bead158552fd8093867ea13a78527d707cee618..e50a69c434f99a39e771b9856622e0bd0ec0eef6 100644 --- a/api_documentation/api_documentation.go +++ b/api_documentation/api_documentation.go @@ -12,10 +12,9 @@ import ( type NoParams struct{} type DocPath map[string]DocMethodInfo - type Docs struct { - Paths map[string]DocPath `json:"paths"` - Components DocSchemas `json:"components"` + Paths map[string]DocPath `json:"paths"` + Components DocSchemas `json:"components"` } type DocSchemas struct { @@ -23,46 +22,43 @@ type DocSchemas struct { } type DocMethodInfo struct { - Description string `json:"description"` - Tags []string `json:"tags"` - RequestBody *DocRequestBody `json:"requestBody,omitempty"` - Parameters []DocParam `json:"parameters,omitempty"` - Responses *map[string]DocResponseValue `json:"responses,omitempty"` + Description string `json:"description"` + Tags []string `json:"tags"` + RequestBody *DocRequestBody `json:"requestBody,omitempty"` + Parameters []DocParam `json:"parameters,omitempty"` + Responses *map[string]DocResponseValue `json:"responses,omitempty"` } type DocRequestBody struct { - Description string `json:"description"` - Required bool `json:"required"` - Content map[string]interface{} `json:"content"` + Description string `json:"description"` + Required bool `json:"required"` + Content map[string]interface{} `json:"content"` } - type DocParam struct { - Name string `json:"name"` - In string `json:"in"` - Description string `json:"description"` - Schema interface{} `json:"schema"` + Name string `json:"name"` + In string `json:"in"` + Description string `json:"description"` + Schema interface{} `json:"schema"` } - type DocSchema struct { Ref string `json:"$ref"` } type DocResponseValue struct { - Description string `json:"description"` - Content map[string]interface{} `json:"content"` + Description string `json:"description"` + Content *map[string]interface{} `json:"content,omitempty"` } type DocSchemaResponse struct { - Type *string `json:"type,omitempty"` - Items DocSchema `json:"items"` + Type *string `json:"type,omitempty"` + Items DocSchema `json:"items"` } - func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { docs := Docs{ - Paths: map[string]DocPath{}, + Paths: map[string]DocPath{}, Components: DocSchemas{Schemas: map[string]interface{}{}}, } @@ -71,7 +67,6 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { return Docs{}, validationError } - for path, methods := range endpointHandlers { docPath := DocPath{} for method, methodHandler := range methods { @@ -79,11 +74,11 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { if handler, ok := methodHandler.(handler_utils.Handler); !ok { docMethod.Description = "Not available" } else { - //purpose + // purpose docMethod.Description = "Not available - see request and response structs" docMethod.Tags = []string{path} - //describe parameters + // describe parameters docMethod.Parameters = []DocParam{} for i := 0; i < handler.RequestParamsType.NumField(); i++ { f := handler.RequestParamsType.Field(i) @@ -99,67 +94,69 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { return Docs{}, err } - parameter := DocParam{ Name: name, - In: "query", + In: "query", Description: f.Tag.Get("doc"), - Schema: schema, + Schema: schema, } docMethod.Parameters = append(docMethod.Parameters, parameter) } // Request - if handler.RequestBodyType != nil { - body := reflect.New(handler.RequestBodyType).Interface() - bodyTypeString := getType(body) - - - docMethod.RequestBody = &DocRequestBody{ - Description: "Some description", - Required: true, - Content: map[string]interface{} { - "application/json": map[string]interface{}{ - "schema": DocSchema{Ref: "#/components/schemas/"+bodyTypeString}, - }, - }, - } - - if handler.RequestBodyType.Kind() == reflect.Struct && handler.RequestBodyType.NumField() > 0 { - schema, err := StructSchema(handler.RequestBodyType.Field(0).Type) - if err != nil { - return Docs{}, err - } - docs.Components.Schemas[bodyTypeString] = schema - } - } + if handler.RequestBodyType != nil { + body := reflect.New(handler.RequestBodyType).Interface() + bodyTypeString := getType(body) + + docMethod.RequestBody = &DocRequestBody{ + Description: "Some description", + Required: true, + Content: map[string]interface{}{ + "application/json": map[string]interface{}{ + "schema": DocSchema{Ref: "#/components/schemas/" + bodyTypeString}, + }, + }, + } + + if handler.RequestBodyType.Kind() == reflect.Struct && handler.RequestBodyType.NumField() > 0 { + schema, err := StructSchema(handler.RequestBodyType.Field(0).Type) + if err != nil { + return Docs{}, err + } + docs.Components.Schemas[bodyTypeString] = schema + } + } // Response - if handler.ResponseType != nil { - responses := map[string]DocResponseValue{} - responseBody := reflect.New(handler.ResponseType).Interface() - responseBodyTypeString := getType(responseBody) - - responses["200"] = DocResponseValue{ - Description: "Some description", - Content: map[string]interface{} { - "application/json": map[string]interface{}{ - "schema": DocSchema{Ref: "#/components/schemas/"+responseBodyTypeString}, - }, - }, - } - - docMethod.Responses = &responses - - if handler.ResponseType.Kind() == reflect.Struct && handler.ResponseType.NumField() > 0 { - schema, err := StructSchema(handler.ResponseType.Field(0).Type) - if err != nil { - return Docs{}, err - } - docs.Components.Schemas[responseBodyTypeString] = schema - } - } + if handler.ResponseType != nil { + responses := map[string]DocResponseValue{} + responseBody := reflect.New(handler.ResponseType).Interface() + responseBodyTypeString := getType(responseBody) + + response := DocResponseValue{ + Description: "Some description", + } + responses["200"] = response + + if responseBodyTypeString != "" { + response.Content = &map[string]interface{}{ + "application/json": map[string]interface{}{ + "schema": DocSchema{Ref: "#/components/schemas/" + responseBodyTypeString}, + }, + } + } + + docMethod.Responses = &responses + + if handler.ResponseType.Kind() == reflect.Struct && handler.ResponseType.NumField() > 0 { + schema, err := StructSchema(handler.ResponseType.Field(0).Type) + if err != nil { + return Docs{}, err + } + docs.Components.Schemas[responseBodyTypeString] = schema + } + } } docPath[strings.ToLower(method)] = docMethod @@ -167,7 +164,6 @@ func GetDocs(endpointHandlers map[string]map[string]interface{}) (Docs, error) { docs.Paths[path] = docPath } - return docs, nil } @@ -185,10 +181,8 @@ func StructSchema(t reflect.Type) (interface{}, error) { } schema := map[string]interface{}{} - description := "" - if t.Kind() == reflect.Ptr { // schema["optional"] = true t = t.Elem() @@ -198,25 +192,25 @@ func StructSchema(t reflect.Type) (interface{}, error) { case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: schema["type"] = "integer" - schema["format"] = fmt.Sprintf("%v", t) + schema["format"] = fmt.Sprintf("%v", t) case reflect.Float64, reflect.Float32: schema["type"] = "number" - schema["format"] = fmt.Sprintf("%v", t) + schema["format"] = fmt.Sprintf("%v", t) case reflect.Bool: schema["type"] = "boolean" - schema["format"] = fmt.Sprintf("%v", t) + schema["format"] = fmt.Sprintf("%v", t) case reflect.String: schema["type"] = "string" - schema["format"] = fmt.Sprintf("%v", t) + schema["format"] = fmt.Sprintf("%v", t) case reflect.Interface: - schema["type"] = "object" //any value...? + schema["type"] = "object" // any value...? case reflect.Struct: if t.String() == "time.Time" { schema["type"] = "string" - schema["format"] = "date" + schema["format"] = "date" return schema, nil } @@ -231,12 +225,10 @@ func StructSchema(t reflect.Type) (interface{}, error) { fieldName = f.Name } if fieldName == "-" { - continue //json does not marshal these + continue // json does not marshal these } fieldName = strings.Replace(fieldName, ",omitempty", "", -1) - - var err error fieldDesc := f.Tag.Get("doc") if fieldDesc == "" {