Skip to content
Snippets Groups Projects
Select Git revision
  • 515ab5b39912999c040f9252b238f6a211318826
  • main default protected
  • v1.298.0
  • v1.297.0
  • v1.296.0
  • v1.295.0
  • v1.294.0
  • v1.293.0
  • v1.292.0
  • v1.291.0
  • v1.290.0
  • v1.289.0
  • v1.288.0
  • v1.287.0
  • v1.286.0
  • v1.285.0
  • v1.284.0
  • v1.283.0
  • v1.282.0
  • v1.281.0
  • v1.280.0
  • v1.279.0
22 results

api_documentation.go

Blame
  • api_documentation.go 6.08 KiB
    package api_documentation
    
    import (
    	"fmt"
    	"reflect"
    	"strings"
    
    	"gitlab.com/uafrica/go-utils/handler_utils"
    )
    
    type NoParams struct{}
    type DocPath map[string]DocMethodInfo
    
    
    type Docs struct {
    	Paths map[string]DocPath `json:"paths"`
    	Definitions map[string]interface{}
    }
    
    
    type DocMethodInfo struct {
    	Summary    string              `json:"summary"`
    	Tags []string `json:"tags"`
    	Parameters []DocParam `json:"parameters,omitempty"`
    	Responses    map[string]DocResponseValue         `json:"responses,omitempty"`
    }
    
    type DocParam struct {
    	Name        string
    	In string
    	Type        string
    	Description string
    	Schema DocSchema
    }
    
    type DocSchema struct {
    	Ref string `json:"$ref"`
    }
    
    type DocResponseValue struct {
    	Description string  `json:"description"`
    	Schema      *DocSchemaResponse `json:"schema,omitempty"`
    }
    
    type DocSchemaResponse struct {
    	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{},
    	}
    
    	var validationError error
    	if endpointHandlers, validationError = handler_utils.ValidateAPIEndpoints(endpointHandlers); validationError != nil {
    		return Docs{}, validationError
    	}
    
    
    	for path, methods := range endpointHandlers {
    		docPath := DocPath{}
    		for method, methodHandler := range methods {
    			docMethod := DocMethodInfo{}
    			if handler, ok := methodHandler.(handler_utils.Handler); !ok {
    				docMethod.Summary = "Not available"
    			} else {
    				//purpose
    				docMethod.Summary = "Not available - see request and response structs"
    				docMethod.Tags = []string{path}
    
    				//describe parameters
    				docMethod.Parameters = []DocParam{}
    				for i := 0; i < handler.RequestParamsType.NumField(); i++ {
    					f := handler.RequestParamsType.Field(i)
    
    					name := f.Tag.Get("json")
    					if name == "" {
    						name = f.Name
    					}
    
    					parameter := DocParam{
    						Name:        name,
    						Type:        fmt.Sprintf("%v", f.Type),
    						Description: f.Tag.Get("doc"),
    					}
    
    					docMethod.Parameters = append(docMethod.Parameters, parameter)
    				}
    
    				// Request
    				 if handler.RequestBodyType != nil {
    					 body := reflect.New(handler.RequestBodyType).Interface()
    					 bodyTypeString := getType(body)
    					 parameter := DocParam{
    						 Name:        "body",
    						 In: 		"body",
    						 Schema: DocSchema{Ref: "#/definitions/"+bodyTypeString},
    					 }
    
    					 docMethod.Parameters = append(docMethod.Parameters, parameter)
    					 docs.Definitions[bodyTypeString] = ""
    				 }
    
    				// Response
    				 if handler.ResponseType != nil {
    					 responses := map[string]DocResponseValue{}
    					 responseBody := reflect.New(handler.RequestBodyType).Interface()
    					 responseBodyTypeString := getType(responseBody)
    
    					 responses["200"] = DocResponseValue{
    						 Description: "successful operation",
    						 Schema: &DocSchemaResponse{
    							 Items: DocSchema{Ref:  "#/definitions/"+responseBodyTypeString},
    						 },
    					 }
    
    					 docMethod.Responses = responses
    					 docs.Definitions[responseBodyTypeString] = ""
    				 }
    
    
    
    
    
    				//describe request schema
    				// var err error
    				// docMethod.Request, err = DocSchema(fmt.Sprintf("%s %s %s", method, path, "request"), handler.RequestBodyType)
    				// if err != nil {
    				// 	return Docs{}, errors.Wrapf(err, "failed to document request")
    				// }
    				// docMethod.Response, err = DocSchema(fmt.Sprintf("%s %s %s", method, path, "response"), handler.ResponseType)
    				// if err != nil {
    				// 	return Docs{}, errors.Wrapf(err, "failed to document response")
    				// }
    			}
    
    			docPath[strings.ToLower(method)] = docMethod
    		}
    		docs.Paths[path] = docPath
    	}
    
    
    	return docs, nil
    }
    
    func getType(myvar interface{}) string {
    	if t := reflect.TypeOf(myvar); t.Kind() == reflect.Ptr {
    		return t.Elem().Name()
    	} else {
    		return t.Name()
    	}
    }
    //
    // func DocSchema(description string, t reflect.Type) (interface{}, error) {
    // 	if t == nil {
    // 		return nil, nil
    // 	}
    // 	schema := map[string]interface{}{
    // 		"description": description,
    // 	}
    //
    // 	if t.Kind() == reflect.Ptr {
    // 		schema["optional"] = true
    // 		t = t.Elem()
    // 	}
    //
    // 	switch t.Kind() {
    // 	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int,
    // 		reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint,
    // 		reflect.Float64, reflect.Float32,
    // 		reflect.Bool,
    // 		reflect.String:
    // 		schema["type"] = fmt.Sprintf("%v", t)
    //
    // 	case reflect.Interface:
    // 		schema["type"] = "interface{}" //any value...?
    //
    // 	case reflect.Struct:
    // 		schema["type"] = "object"
    // 		properties := map[string]interface{}{}
    // 		for i := 0; i < t.NumField(); i++ {
    // 			f := t.Field(i)
    // 			if !f.Anonymous {
    // 				fieldName := f.Tag.Get("json")
    // 				if fieldName == "" {
    // 					fieldName = f.Name
    // 				}
    // 				if fieldName == "-" {
    // 					continue //json does not marshal these
    // 				}
    // 				fieldName = strings.Replace(fieldName, ",omitempty", "", -1)
    //
    // 				var err error
    // 				fieldDesc := f.Tag.Get("doc")
    // 				if fieldDesc == "" {
    // 					fieldDesc = description + "." + fieldName
    // 				}
    // 				properties[fieldName], err = DocSchema(fieldDesc, f.Type)
    // 				if err != nil {
    // 					return nil, errors.Wrapf(err, "failed to document %v.%s", t, fieldName)
    // 				}
    // 			}
    // 		}
    // 		schema["properties"] = properties
    //
    // 	case reflect.Map:
    // 		schema["type"] = "map"
    // 		// keySchema, err := DocSchema("key", t.Key())
    // 		// if err != nil {
    // 		// 	return nil, errors.Wrapf(err, "cannot make schema for %v map key", t)
    // 		// }
    // 		// schema["key"] = keySchema
    // 		// // elemSchema, err := DocSchema("items", t.Elem())
    // 		// if err != nil {
    // 		// 	return nil, errors.Wrapf(err, "cannot make schema for %v map elem", t)
    // 		// }
    // 		// schema["items"] = elemSchema
    //
    // 	case reflect.Slice:
    // 		schema["type"] = "array"
    // 		// elemSchema, err := DocSchema("items", t.Elem())
    // 		// if err != nil {
    // 		// 	return nil, errors.Wrapf(err, "cannot make schema for %v slice elem", t)
    // 		// }
    // 		// schema["items"] = elemSchema
    //
    // 	default:
    // 		return nil, errors.Errorf("cannot generate schema for %v kind=%v", t, t.Kind())
    // 	}
    //
    // 	return schema, nil
    // }