func (h *Handler) findEnterFunc(t reflect.Type) *reflect.Method { method, ok := t.MethodByName(flaglyEnter) if ok { return &method } return nil }
func compileField(typ reflect.Type, name string, args []parse.Node, final reflect.Type) (fn lookupFn, elem reflect.Type) { if isNilType(typ) { fn = compileFieldDynamic(name, args) return } if m, exist := typ.MethodByName(name); exist { fn = compileMethodCall(typ, m.Func, args, final) elem = m.Type.Out(0) return } switch typ.Kind() { case reflect.Struct: structField, found := typ.FieldByName(name) if !found { panic(fmt.Errorf("%s has no field %s", typ, name)) } fn = func(s state, v reflect.Value, final interface{}) reflect.Value { return v.FieldByIndex(structField.Index) } elem = structField.Type return case reflect.Map: k := reflect.ValueOf(name) fn = func(s state, v reflect.Value, final interface{}) reflect.Value { return v.MapIndex(k) } elem = typ.Key() return } panic(fmt.Errorf("struct or map expected, but got %s", typ)) }
func CheckMethod(t *testing.T, typ reflect.Type, desc Method) { method, found := typ.MethodByName(desc.Name) if !found { t.Fatalf("Le type %v ne définit pas de méthode '%s'", typ, desc.Name) } if method.Type.NumIn() != len(desc.InTypes)+1 { t.Fatalf("La méthode %v.%s doit prendre %d paramètre(s)", typ, desc.Name, len(desc.InTypes)) } if method.Type.NumOut() != len(desc.OutTypes) { t.Fatalf("La méthode %v.%s doit renvoyer %d résultat(s)", typ, desc.Name, len(desc.OutTypes)) } for i, inType := range desc.InTypes { if method.Type.In(i+1) != inType { t.Fatalf("La méthode %v.%s doit prendre un type %v en paramètre #%d", typ, desc.Name, inType, i+1) } } for i, outType := range desc.OutTypes { if method.Type.Out(i) != outType { t.Fatalf("La méthode %v.%s doit renvoyer un type %v en résultat #%d", typ, desc.Name, outType, i+1) } } }
func (info *Info) addMethods(jt *Type, t reflect.Type) { // Add any methods. var vt reflect.Type if t.Kind() != reflect.Interface && !isWithoutReceiver(t) { t = reflect.PtrTo(t) vt = t.Elem() } for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) if m.PkgPath != "" { continue } if t.Kind() != reflect.Interface { m.Type = withoutReceiverType{m.Type} } jm := Method{ Name: m.Name, Type: info.Ref(m.Type), } if vt != nil { _, hasValueMethod := vt.MethodByName(m.Name) jm.PtrReceiver = !hasValueMethod } if jt.Methods == nil { jt.Methods = make(map[string]*Method) } jt.Methods[jm.Name] = &jm } }
func dispose(v uintptr, t r.Type) { if m, ok := t.MethodByName("Dispose"); ok { // && m.Func.Type().NumIn() == 2 { f := m.Func tv := r.NewAt(f.Type().In(1).Elem(), unsafe.Pointer(v)) f.Call([]r.Value{r.New(t).Elem(), tv}) } }
func missingMethod(iT, xT reflect.Type) (method string) { numMethod := iT.NumMethod() for i := 0; i < numMethod; i += 1 { method = iT.Method(i).Name if _, ok := xT.MethodByName(method); !ok { return } } return "" }
func getMapMethods(baseType reflect.Type) (get, set reflect.Type, err error) { getAll, ok := baseType.MethodByName("GetAll") if !ok { return nil, nil, errors.Errorf("no method named GetAll") } setAll, ok := baseType.MethodByName("SetAll") if !ok { return nil, nil, errors.Errorf("no method named SetAll") } return getAll.Type, setAll.Type, nil }
func MethodsMissingFromType(inter, typ reflect.Type) []string { missingMethods := make([]string, 0) for n := 0; n < inter.NumMethod(); n++ { _, present := typ.MethodByName(inter.Method(n).Name) if !present { fmt.Println(inter.Method(n).Name) missingMethods = append(missingMethods, inter.Method(n).Name) } } return missingMethods }
func enumSymbols(t reflect.Type) []string { if _, ok := t.MethodByName("SymbolSet"); ok { //an enum type that RDL generated. Create a dummy instance and call to get the symbol set tmp := reflect.New(t) vv := tmp.Elem() vv.SetInt(1) symbols := tmp.MethodByName("SymbolSet").Call([]reflect.Value{})[0].Interface() return symbols.([]string)[1:] } return nil }
func findParameterGetMethod(handlerParametersType reflect.Type, field reflect.Type) (reflect.Method, bool) { var name []rune switch field.Kind() { case reflect.Ptr: name = []rune(field.Elem().Kind().String()) default: name = []rune(field.Kind().String()) } name[0] = unicode.ToUpper(name[0]) methodName := "Get" + string(name) return handlerParametersType.MethodByName(methodName) }
func methodValue(key string, typ reflect.Type) (mapFunc, reflect.Type, error) { if m, ok := typ.MethodByName(key); ok { if m.Type.NumIn() > 1 { return nil, nil, fmt.Errorf("method %s on type %s has %d arguments, must have none", key, typ, m.Type.NumIn()-1) } if m.Type.NumOut() != 1 { return nil, nil, fmt.Errorf("method %s on type %s returns %d values, must return one", key, typ, m.Type.NumOut()) } return methodValueFunc(m), m.Type.Out(0), nil } return nil, nil, nil }
func getTypes(t reflect.Type, s supportingTypes, c *int) *Type { n, p := t.String(), t.PkgPath() if _, ok := t.MethodByName("MarshalJSON"); ok { return custom(n, p) } switch t.Kind() { case reflect.String: return simple(String) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return simple(Int) case reflect.Float32, reflect.Float64: return simple(Float) case reflect.Bool: return simple(Bool) case reflect.Ptr: return s.set(n, p, func() *Type { return ptrOf(getTypes(t.Elem(), s, c)) }) case reflect.Array, reflect.Slice: if t.Elem().Kind() == reflect.Uint8 { return simple(Bytes) } return s.set(n, p, func() *Type { return arrayOf(getTypes(t.Elem(), s, c)) }) case reflect.Struct: if p == "" { // gets an anonymous type name and fake the package n = anonTypeName(c) p = "github.com/shutej/go2flow/anonymous" } return s.set(n, p, func() *Type { return structOf(getFields(t, s, c)) }) case reflect.Map: if t.Key().Kind() != reflect.String { log.Fatalf("unexpected map key type: %v", t.Key()) } return s.set(n, p, func() *Type { return mapOf(getTypes(t.Elem(), s, c)) }) } log.Fatalf("unknown kind for type: %v", t) return nil }
func createTypeDescribe(typ reflect.Type) *typeDescribe { td := &typeDescribe{} td.initMethod, td.hasInitMethod = typ.MethodByName("PostConstruct") for typ.Kind() == reflect.Ptr { typ = typ.Elem() } for i := 0; i < typ.NumField(); i++ { f := typ.Field(i) tag := f.Tag.Get("inject") if tag != "" { td.fields = append(td.fields, f) } } typeDescribes[typ.String()] = td return td }
func go2jsonType(t reflect.Type, canAddr bool) *Type { if _, ok := t.MethodByName("MarshalJSON"); ok { return CustomType(t.String()) } if canAddr { if _, ok := reflect.PtrTo(t).MethodByName("MarshalJSON"); ok { return CustomType(t.String()) } } switch t.Kind() { case reflect.Bool: return SimpleType(Bool) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64: return SimpleType(Number) case reflect.String: return SimpleType(String) case reflect.Complex64, reflect.Complex128: return CustomType("complex") case reflect.Chan: return CustomType("chan") case reflect.Array, reflect.Slice: return ArrayOf(go2jsonType(t.Elem(), canAddr || t.Kind() == reflect.Slice)) case reflect.Map: if t.Key().Kind() != reflect.String { // TODO better error recovery panic("unexpected map key kind") } return MapOf(go2jsonType(t.Elem(), false)) case reflect.Ptr: return NullableOf(go2jsonType(t.Elem(), true)) case reflect.Struct: return ObjectOf(jsonFields(t, canAddr)) case reflect.UnsafePointer: return CustomType("unsafe.Pointer") case reflect.Interface: return CustomType("any") case reflect.Func: return CustomType("func") } panic(fmt.Errorf("unknown kind for type %s", t)) }
func (p *Page) callMethod(tpc reflect.Type, vpc reflect.Value, action string, rvr reflect.Value, rvw reflect.Value) []reflect.Value { arv := []reflect.Value{} if rm, ok := tpc.MethodByName(action); ok { mt := rm.Type switch mt.NumIn() { case 2: if mt.In(1) == rvr.Type() { arv = vpc.MethodByName(action).Call([]reflect.Value{rvr}) } else { arv = vpc.MethodByName(action).Call([]reflect.Value{rvw}) } case 3: arv = vpc.MethodByName(action).Call([]reflect.Value{rvw, rvr}) default: arv = vpc.MethodByName(action).Call([]reflect.Value{}) } } return arv }
// Route registers a route by method name. func (r *Router) Route(path, name string, context reflect.Type, methods []string) error { rule, err := r.Rule(path, name, methods) if err != nil { return err } parts := strings.Split(name, ".") method, ok := context.MethodByName(parts[len(parts)-1]) if !ok { return nil // change } r.endpoints[rule] = &endpoint{ context: context, method: method.Func, bindings: make(map[string]interface{}), } return nil }
func MakeMethods(typ reflect.Type) (m *Methods, err error) { m = &Methods{-1, -1} // Get pointer methods if typ.Kind() != reflect.Ptr { typ = reflect.PtrTo(typ) } // Check for Load and Save methods if load, ok := typ.MethodByName("Load"); ok { if err = checkMethod(typ, load); err != nil { return } m.LoadIndex = load.Index } if save, ok := typ.MethodByName("Save"); ok { if err = checkMethod(typ, save); err != nil { return } m.SaveIndex = save.Index } return }
// GetMissingMethods checks if a given object implements all methods of a // given interface. It returns the interface coverage [0..1] as well as an array // of error messages. If the interface is correctly implemented the coverage is // 1 and the error message array is empty. func GetMissingMethods(objType reflect.Type, ifaceType reflect.Type) (float32, []interface{}) { var missing []interface{} if objType.Implements(ifaceType) { return 1.0, missing } methodCount := ifaceType.NumMethod() for mIdx := 0; mIdx < methodCount; mIdx++ { ifaceMethod := ifaceType.Method(mIdx) objMethod, exists := objType.MethodByName(ifaceMethod.Name) signatureMismatch := false switch { case !exists: missing = append(missing, fmt.Sprintf("Missing: \"%s\" %v", ifaceMethod.Name, ifaceMethod.Type)) continue // ### continue, error found ### case ifaceMethod.Type.NumOut() != objMethod.Type.NumOut(): signatureMismatch = true case ifaceMethod.Type.NumIn()+1 != objMethod.Type.NumIn(): signatureMismatch = true default: for oIdx := 0; !signatureMismatch && oIdx < ifaceMethod.Type.NumOut(); oIdx++ { signatureMismatch = ifaceMethod.Type.Out(oIdx) != objMethod.Type.Out(oIdx) } for iIdx := 0; !signatureMismatch && iIdx < ifaceMethod.Type.NumIn(); iIdx++ { signatureMismatch = ifaceMethod.Type.In(iIdx) != objMethod.Type.In(iIdx+1) } } if signatureMismatch { missing = append(missing, fmt.Sprintf("Invalid: \"%s\" %v is not %v", ifaceMethod.Name, objMethod.Type, ifaceMethod.Type)) } } return float32(methodCount-len(missing)) / float32(methodCount), missing }
func AddApis(am Apis) { for _, a := range am { f := r.ValueOf(a.Fnc) if f.Kind() != r.Ptr { panic("outside: " + r.TypeOf(a.Fnc).String() + " supplied : Pointer to function expected") } fn := f.Elem() fnt := fn.Type() var apiCall func(i []r.Value) []r.Value //Allow 2 returns and put err in 2nd if supplied var ot, et r.Type nOut := fnt.NumOut() if nOut >= 1 { ot = fnt.Out(0) } if nOut == 2 { et = fnt.Out(1) } p, unicode := apiAddr(a.Ep) if p != nil { fai, sli, fao, slo := funcAnalysis(fnt) // name := a.Ep retSizeArg := -1 if nOut >= 1 && ot.Kind() == r.Slice { if sa, ok := ot.MethodByName("SizeArg"); ok { retSizeArg = int(sa.Func.Call([]r.Value{r.Indirect(r.New(ot))})[0].Int() - 1) } } var hasErrorMethod bool var ea r.Method if ot != nil { ea, hasErrorMethod = ot.MethodByName("Error") } apiCall = func(i []r.Value) []r.Value { TOT++ var rr r.Value inStructs(unicode, i, fai, sli) ina := inArgs(unicode, i) r1, r2, f, err := p.call(ina...) // Printf("%s %v %v %b %x %b %x\n", name, i, ot, fai, sli, fao, slo) outStructs(unicode, i, fao, slo) if ot != nil { if runtime.GOARCH == "amd64" || ot.Size() == 4 { rr = r.ValueOf(r1) } else if fnt.Out(0).Kind() == r.Float64 || fnt.Out(0).Kind() == r.Float32 { rr = r.ValueOf(f) } else { rr = r.ValueOf((uint64(r2) << 32) | uint64(r1)) } vrsa := rsaNo if retSizeArg != -1 { vrsa = i[retSizeArg] } v1 := convert(rr, ot, unicode, vrsa) if hasErrorMethod { // TODO(t): for linux - error strategy var ret []r.Value if err == nil { ret = ea.Func.Call([]r.Value{v1, r.Zero(r.TypeOf(new(error)).Elem())}) // issue 6871 } else { ret = ea.Func.Call([]r.Value{v1, r.ValueOf(err)}) } v1 = ret[0] if e := ret[1].Interface(); e != nil { err = e.(error) } else { err = nil } } if et == nil { return []r.Value{v1} } else { return []r.Value{v1, convert(r.ValueOf(err), et, unicode, rsaNo)} } } else { return nil } } } else { apiCall = func(i []r.Value) []r.Value { panic(`outside: call of non-existent procedure "` + string(a.Ep) + `"`) } } v := r.MakeFunc(fn.Type(), apiCall) fn.Set(v) } }
// From the endpoint, defined in the Service struct, init the variables and the server listeners. // Besides, load de configuration file to start basic data required for the proposed solution. func initSvc(svcElem EndPointHandler) (*Service, error) { var err error var i int var resp *Service var cfg Shaper var ls net.Listener var met reflect.Method var ok bool var typ reflect.Type var fld reflect.StructField var auth AuthT resp = &Service{ // AuthRequired: false, MatchedOps: map[int]int{}, } cfg, err = svcElem.GetConfig() if err != nil { Goose.Initialize.Logf(1, "Failed opening config: %s", err) return nil, err } if cfg == nil { return nil, nil } /* //TODO: shaper -> remover err = json.NewDecoder(cfg).Decode(&resp) if (err!=nil) && (err!=io.EOF) { Goose.Initialize.Logf(1,"Failed parsing config file: %s", err) return nil, err } */ resp.Config = cfg ls, err = net.Listen("tcp", cfg.ListenAddress()) if err != nil { Goose.Initialize.Logf(1, "Failed creating listener: %s", err) return nil, err } resp.Listener, err = NewListener(ls) if err != nil { Goose.Initialize.Logf(1, "Failed creating stoppable listener: %s", err) return nil, err } ls, err = net.Listen("tcp", cfg.CRLListenAddress()) if err != nil { Goose.Initialize.Logf(1, "Failed creating listener: %s", err) return nil, err } resp.CRLListener, err = NewListener(ls) if err != nil { Goose.Initialize.Logf(1, "Failed creating stoppable listener: %s", err) return nil, err } typ = reflect.ValueOf(svcElem).Type() if typ.Kind() == reflect.Ptr { typ = typ.Elem() } met, ok = typ.MethodByName("SavePending") if ok { resp.SavePending = func(info interface{}) error { var err error errIFace := met.Func.Call([]reflect.Value{reflect.ValueOf(resp.Config), reflect.ValueOf(info)})[0].Interface() switch errIFace.(type) { case error: err = errIFace.(error) } if err != nil { Goose.Auth.Logf(1, "Internal server error saving unauthorized access attempt info: %s", err) Goose.Auth.Logf(5, "Dump of info on internal server error saving unauthorized access attempt info: %#v", info) } return err } } else { resp.SavePending = func(interface{}) error { return nil } } Goose.Auth.Logf(5, "cfg: %#v", cfg) Goose.Auth.Logf(5, "cfg.CertKit(): %#v", cfg.CertKit()) Goose.Auth.Logf(5, "auth: %#v", auth) Goose.Auth.Logf(5, "auth: %#v", reflect.TypeOf((*AuthT)(nil)).Elem()) if cfg.CertKit() != nil && reflect.TypeOf(cfg.CertKit()).Implements(reflect.TypeOf((*AuthT)(nil)).Elem()) { resp.Authorizer = cfg.CertKit() } else { resp.Authorizer = PublicAccessT{} } for i = 0; i < typ.NumField(); i++ { fld = typ.Field(i) if fld.Anonymous && fld.Type.Implements(reflect.TypeOf((*AuthT)(nil)).Elem()) { resp.Authorizer = reflect.ValueOf(svcElem).Field(i).Interface().(AuthT) break } } return resp, err }
func New(svcs ...EndPointHandler) (*Service, error) { var resp *Service var svc EndPointHandler var svcElem EndPointHandler var svcRecv reflect.Value var consumes string var svcConsumes string var produces string var svcProduces string var allowGzip string var enableCORS string var proto []string var svcProto []string var svcRoot string var i, j, k int var typ reflect.Type var typPtr reflect.Type var pt []reflect.Type var fld reflect.StructField var method reflect.Method var parmcount int var httpmethod, path string var methodName string var tk string var ok bool var re string var reAllOps string var reComp *regexp.Regexp var c rune var err error var stmp string var SwaggerParameter *SwaggerParameterT var swaggerParameters []SwaggerParameterT var swaggerInfo SwaggerInfoT var swaggerLicense SwaggerLicenseT var swaggerContact SwaggerContactT var globalDataCount int var responseOk string var responseCreated string var responseAccepted string var responses map[string]SwaggerResponseT var fldType reflect.Type var doc string var description *string var headers []string var query []string var optIndex map[string]int var HdrNew, HdrOld string var MatchedOpsIndex int var postFields []string var postField string var postdata string // var accesstype uint8 var parmnames []string for _, svc = range svcs { Goose.New.Logf(6, "Elem: %#v (Kind: %#v)", reflect.ValueOf(svc), reflect.ValueOf(svc).Kind()) if reflect.ValueOf(svc).Kind() == reflect.Ptr { Goose.New.Logf(6, "Elem: %#v", reflect.ValueOf(svc).Elem()) svcElem = reflect.ValueOf(svc).Elem().Interface().(EndPointHandler) Goose.New.Logf(6, "Elem type: %s, ptr type: %s", reflect.TypeOf(svcElem), reflect.TypeOf(svc)) } else { svcElem = svc Goose.New.Logf(6, "Elem type: %s", reflect.TypeOf(svcElem)) } // The first endpoint handler MUST have a config defined, otherwise we'll ignore endpoint handlers until we find one which provides a configuration if resp == nil { resp, err = initSvc(svcElem) if err != nil { return nil, err } if resp == nil { continue // If we still don't have a config defined and the endpoint handler has no config defined it WILL BE IGNORED!!! } } typ = reflect.ValueOf(svcElem).Type() if typ.Kind() == reflect.Ptr { typPtr = typ typ = typ.Elem() } else { typPtr = reflect.PtrTo(typ) } if resp.Swagger == nil { for i = 0; (i < typ.NumField()) && (globalDataCount < 4); i++ { if svcRoot == "" { svcRoot = typ.Field(i).Tag.Get("root") if svcRoot != "" { svcConsumes = typ.Field(i).Tag.Get("consumes") svcProduces = typ.Field(i).Tag.Get("produces") allowGzip = typ.Field(i).Tag.Get("allowGzip") enableCORS = typ.Field(i).Tag.Get("enableCORS") if typ.Field(i).Tag.Get("proto") != "" { svcProto = strings.Split(strings.ToLower(strings.Trim(typ.Field(i).Tag.Get("proto"), " ")), ",") } else { svcProto = []string{"https"} } Goose.New.Logf(3, "Access tag: %s", typ.Field(i).Tag.Get("access")) if typ.Field(i).Tag.Get("access") != "" { switch strings.ToLower(strings.Trim(typ.Field(i).Tag.Get("access"), " ")) { case "none": resp.Access = AccessNone case "auth": resp.Access = AccessAuth case "authinfo": resp.Access = AccessAuthInfo case "verifyauth": resp.Access = AccessVerifyAuth case "verifyauthinfo": resp.Access = AccessVerifyAuthInfo } Goose.New.Logf(3, "Custom access type: %d", resp.Access) } else { resp.Access = AccessAuthInfo Goose.New.Logf(3, "Default access type: %d", resp.Access) } globalDataCount++ } } if swaggerInfo.Title == "" { stmp = typ.Field(i).Tag.Get("title") if stmp != "" { swaggerInfo.Title = stmp swaggerInfo.Description = typ.Field(i).Tag.Get("description") swaggerInfo.TermsOfService = typ.Field(i).Tag.Get("tos") swaggerInfo.Version = typ.Field(i).Tag.Get("version") globalDataCount++ } } if swaggerContact.Name == "" { stmp = typ.Field(i).Tag.Get("contact") if stmp != "" { swaggerContact.Name = stmp swaggerContact.Url = typ.Field(i).Tag.Get("url") swaggerContact.Email = typ.Field(i).Tag.Get("email") globalDataCount++ } } if swaggerLicense.Name == "" { stmp = typ.Field(i).Tag.Get("license") if stmp != "" { swaggerLicense.Name = stmp swaggerLicense.Url = typ.Field(i).Tag.Get("url") globalDataCount++ } } } swaggerInfo.Contact = swaggerContact swaggerInfo.License = swaggerLicense svcRoot = strings.Trim(strings.Trim(svcRoot, " "), "/") + "/" svcConsumes = strings.Trim(svcConsumes, " ") svcProduces = strings.Trim(svcProduces, " ") if (svcRoot == "") || (svcConsumes == "") || (svcProduces == "") { Goose.New.Logf(1, "Err: %s", ErrorNoRoot) return nil, ErrorNoRoot } hostport := strings.Split(resp.Config.ListenAddress(), ":") if hostport[0] == "" { hostport[0] = resp.Authorizer.GetDNSNames()[0] } resp.Swagger = &SwaggerT{ Version: "2.0", Info: swaggerInfo, Host: strings.Join(hostport, ":"), BasePath: "/" + svcRoot[:len(svcRoot)-1], Schemes: svcProto, Consumes: []string{svcConsumes}, Produces: []string{svcProduces}, Paths: map[string]SwaggerPathT{}, Definitions: map[string]SwaggerSchemaT{}, } resp.Proto = svcProto Goose.New.Logf(6, "enableCORS: [%s]", enableCORS) if enableCORS != "" { resp.EnableCORS, err = strconv.ParseBool(enableCORS) Goose.New.Logf(6, "resp.EnableCORS: %#v", resp.EnableCORS) if err != nil { Goose.New.Logf(1, "Err: %s", ErrorServiceSyntax) return nil, ErrorServiceSyntax } } Goose.New.Logf(6, "allowGzip: [%s]", allowGzip) if allowGzip != "" { resp.AllowGzip, err = strconv.ParseBool(allowGzip) Goose.New.Logf(6, "resp.AllowGzip: %#v", resp.AllowGzip) if err != nil { Goose.New.Logf(1, "Err: %s", ErrorServiceSyntax) return nil, ErrorServiceSyntax } } } for i = 0; i < typ.NumField(); i++ { fld = typ.Field(i) httpmethod = fld.Tag.Get("method") if httpmethod != "" { methodName = strings.ToUpper(fld.Name[:1]) + fld.Name[1:] svcRecv = reflect.ValueOf(svcElem) if method, ok = typ.MethodByName(methodName); !ok { if method, ok = typPtr.MethodByName(methodName); !ok { Goose.New.Logf(5, "|methods|=%d", typ.NumMethod()) Goose.New.Logf(5, "type=%s.%s", typ.PkgPath(), typ.Name()) for j = 0; j < typ.NumMethod(); j++ { mt := typ.Method(j) Goose.New.Logf(5, "%d: %s", j, mt.Name) } Goose.New.Logf(1, "Method not found: %s, Data: %#v", methodName, typ) return nil, errors.New(fmt.Sprintf("Method not found: %s", methodName)) } else { Goose.New.Logf(1, "Pointer method found, type of svcElem: %s", reflect.TypeOf(svcElem)) svcRecv = reflect.ValueOf(svc) Goose.New.Logf(5, "Pointer method found: %s", methodName) } } path = fld.Tag.Get("path") if _, ok := resp.Swagger.Paths[path]; !ok { resp.Swagger.Paths[path] = SwaggerPathT{} // } else if _, ok := resp.Swagger.Paths[path][httpmethod]; !ok { // resp.Swagger.Paths[path][httpmethod] = SwaggerOperationT{} } swaggerParameters = []SwaggerParameterT{} re = "^" + strings.ToUpper(httpmethod) + ":/" + svcRoot parmcount = 0 parmnames = []string{} for _, tk = range strings.Split(strings.Trim(path, "/"), "/") { if tk != "" { if (tk[0] == '{') && (tk[len(tk)-1] == '}') { re += "([^/]+)/" parmcount++ SwaggerParameter, err = GetSwaggerType(method.Type.In(parmcount)) if err != nil { return nil, err } if SwaggerParameter == nil { return nil, ErrorInvalidNilParam } if (SwaggerParameter.Items != nil) || (SwaggerParameter.CollectionFormat != "") || (SwaggerParameter.Schema.Required != nil) { Goose.New.Logf(1, "%s: %s", tk[1:len(tk)-1]) return nil, ErrorInvalidParameterType } doc = fld.Tag.Get(tk[1 : len(tk)-1]) if doc != "" { description = new(string) (*description) = doc } else { description = SwaggerParameter.Schema.Description if description == nil { description = new(string) } } xkeytype := "" if SwaggerParameter.Schema != nil { xkeytype = SwaggerParameter.Schema.XKeyType } swaggerParameters = append( swaggerParameters, SwaggerParameterT{ Name: tk[1 : len(tk)-1], In: "path", Required: true, Type: SwaggerParameter.Schema.Type, XKeyType: xkeytype, Description: *description, Format: SwaggerParameter.Format, }) parmnames = append(parmnames, tk[1:len(tk)-1]) } else if (tk[0] != '{') && (tk[len(tk)-1] != '}') { for _, c = range tk { re += fmt.Sprintf("\\x{%x}", c) } re += "/" } else { return nil, errors.New("syntax error at " + tk) } } } if resp.Svc == nil { resp.Svc = []UrlNode{} } re += "{0,1}$" Goose.New.Logf(4, "Service "+strings.ToUpper(httpmethod)+":/"+svcRoot+path+", RE="+re) query, parmcount, _, swaggerParameters, err = ParseFieldList("query", parmcount, fld, method, methodName, swaggerParameters) if err != nil { return nil, err } headers, parmcount, _, swaggerParameters, err = ParseFieldList("header", parmcount, fld, method, methodName, swaggerParameters) if err != nil { return nil, err } parmnames = append(parmnames, query...) parmnames = append(parmnames, headers...) postdata = fld.Tag.Get("postdata") if postdata != "" { // Body fields definitions postFields = strings.Split(postdata, ",") pt = make([]reflect.Type, len(postFields)) for k, postField = range postFields { parmcount++ pt[k] = method.Type.In(parmcount) SwaggerParameter, err = GetSwaggerType(pt[k]) if err != nil { return nil, err } if SwaggerParameter == nil { return nil, ErrorInvalidNilParam } doc = fld.Tag.Get(postField) if doc != "" { SwaggerParameter.Schema.Description = new(string) (*SwaggerParameter.Schema.Description) = doc } parmnames = append(parmnames, postField) SwaggerParameter.Name = postField SwaggerParameter.In = "body" SwaggerParameter.Required = true swaggerParameters = append(swaggerParameters, *SwaggerParameter) } /* if resp.Access == AccessAuthInfo || resp.Access == AccessVerifyAuthInfo { parmcount++ } if (parmcount+len(postFields)+1) != method.Type.NumIn() { return nil, errors.New("Wrong parameter count (with post) at method " + methodName) } */ } else { pt = nil } if resp.Access == AccessAuthInfo || resp.Access == AccessVerifyAuthInfo { if (parmcount + 1) != method.Type.NumIn() { parmcount++ if (parmcount + 1) != method.Type.NumIn() { return nil, errors.New("Wrong parameter (with info) count at method " + methodName) } } } else { if (parmcount + 1) != method.Type.NumIn() { return nil, errors.New("Wrong parameter count at method " + methodName) } } Goose.New.Logf(5, "Registering: %s", re) consumes = fld.Tag.Get("consumes") Goose.New.Logf(1, "op:%s consumes: %s tag:%#v", methodName, consumes, fld.Tag) if consumes == "" { consumes = svcConsumes } produces = fld.Tag.Get("produces") if produces == "" { produces = svcProduces } if fld.Tag.Get("proto") != "" { proto = strings.Split(strings.ToLower(strings.Trim(typ.Field(i).Tag.Get("proto"), " ")), ",") } else { proto = svcProto } responses = map[string]SwaggerResponseT{} responseOk = fld.Tag.Get("ok") responseCreated = fld.Tag.Get("created") responseAccepted = fld.Tag.Get("accepted") if responseOk != "" || responseCreated != "" || responseAccepted != "" { if responseOk != "" { fldType = fld.Type if fldType.Kind() == reflect.Ptr { fldType = fldType.Elem() } SwaggerParameter, err = GetSwaggerType(fldType) if err != nil { return nil, err } if SwaggerParameter == nil { responses[fmt.Sprintf("%d", http.StatusNoContent)] = SwaggerResponseT{ Description: responseOk, } } else { doc = fld.Tag.Get(fld.Name) if doc != "" { SwaggerParameter.Schema.Description = new(string) (*SwaggerParameter.Schema.Description) = doc } if SwaggerParameter.Schema == nil { SwaggerParameter.Schema = &SwaggerSchemaT{} } if (SwaggerParameter.Schema.Type == "") && (SwaggerParameter.Type != "") { SwaggerParameter.Schema.Type = SwaggerParameter.Type } responses[fmt.Sprintf("%d", http.StatusOK)] = SwaggerResponseT{ Description: responseOk, Schema: SwaggerParameter.Schema, } //(*responses[fmt.Sprintf("%d",http.StatusOK)].Schema) = *SwaggerParameter.Schema //ioutil.WriteFile("debug.txt", []byte(fmt.Sprintf("%#v",responses)), os.FileMode(0770)) Goose.New.Logf(6, "====== %#v", *(responses[fmt.Sprintf("%d", http.StatusOK)].Schema)) } } if responseCreated != "" { fldType = fld.Type if fldType.Kind() == reflect.Ptr { fldType = fldType.Elem() } SwaggerParameter, err = GetSwaggerType(fldType) if err != nil { return nil, err } if SwaggerParameter == nil { responses[fmt.Sprintf("%d", http.StatusCreated)] = SwaggerResponseT{ Description: responseCreated, } } else { doc = fld.Tag.Get(fld.Name) if doc != "" { SwaggerParameter.Schema.Description = new(string) (*SwaggerParameter.Schema.Description) = doc } if SwaggerParameter.Schema == nil { SwaggerParameter.Schema = &SwaggerSchemaT{} } if (SwaggerParameter.Schema.Type == "") && (SwaggerParameter.Type != "") { SwaggerParameter.Schema.Type = SwaggerParameter.Type } responses[fmt.Sprintf("%d", http.StatusCreated)] = SwaggerResponseT{ Description: responseCreated, Schema: SwaggerParameter.Schema, } //(*responses[fmt.Sprintf("%d",http.StatusOK)].Schema) = *SwaggerParameter.Schema //ioutil.WriteFile("debug.txt", []byte(fmt.Sprintf("%#v",responses)), os.FileMode(0770)) Goose.New.Logf(6, "====== %#v", *(responses[fmt.Sprintf("%d", http.StatusCreated)].Schema)) } } if responseAccepted != "" { fldType = fld.Type if fldType.Kind() == reflect.Ptr { fldType = fldType.Elem() } SwaggerParameter, err = GetSwaggerType(fldType) if err != nil { return nil, err } if SwaggerParameter == nil { responses[fmt.Sprintf("%d", http.StatusAccepted)] = SwaggerResponseT{ Description: responseAccepted, } } else { doc = fld.Tag.Get(fld.Name) if doc != "" { SwaggerParameter.Schema.Description = new(string) (*SwaggerParameter.Schema.Description) = doc } if SwaggerParameter.Schema == nil { SwaggerParameter.Schema = &SwaggerSchemaT{} } if (SwaggerParameter.Schema.Type == "") && (SwaggerParameter.Type != "") { SwaggerParameter.Schema.Type = SwaggerParameter.Type } responses[fmt.Sprintf("%d", http.StatusAccepted)] = SwaggerResponseT{ Description: responseAccepted, Schema: SwaggerParameter.Schema, } //(*responses[fmt.Sprintf("%d",http.StatusOK)].Schema) = *SwaggerParameter.Schema //ioutil.WriteFile("debug.txt", []byte(fmt.Sprintf("%#v",responses)), os.FileMode(0770)) Goose.New.Logf(6, "====== %#v", *(responses[fmt.Sprintf("%d", http.StatusAccepted)].Schema)) } } } else if responseFunc, ok := typ.MethodByName(fld.Name + "Responses"); ok { responseList := responseFunc.Func.Call([]reflect.Value{})[0].Interface().(map[string]ResponseT) for responseStatus, responseSchema := range responseList { SwaggerParameter, err = GetSwaggerType(reflect.TypeOf(responseSchema.TypeReturned)) if err != nil { return nil, err } if SwaggerParameter == nil { responses[responseStatus] = SwaggerResponseT{ Description: responseSchema.Description, } } else { responses[responseStatus] = SwaggerResponseT{ Description: responseSchema.Description, Schema: SwaggerParameter.Schema, } } } } resp.Swagger.Paths[path][strings.ToLower(httpmethod)] = SwaggerOperationT{ Schemes: proto, OperationId: methodName, Parameters: swaggerParameters, Responses: responses, Consumes: []string{consumes}, Produces: []string{produces}, } Goose.New.Logf(5, "Registering marshalers: %s, %s", consumes, produces) resp.MatchedOps[MatchedOpsIndex] = len(resp.Svc) reComp = regexp.MustCompile(re) MatchedOpsIndex += reComp.NumSubexp() + 1 /* switch strings.ToLower(fld.Tag.Get("access")) { case "none": accesstype = AccessNone case "auth": accesstype = AccessAuth case "authinfo": accesstype = AccessAuthInfo default: accesstype = AccessAuth } */ resp.Svc = append(resp.Svc, UrlNode{ Proto: proto, Path: path, consumes: consumes, produces: produces, Headers: headers, Query: query, Body: postFields, ParmNames: parmnames, Handle: buildHandle(svcRecv, method, pt, resp.Access), // Access: resp.Access, }) reAllOps += "|(" + re + ")" Goose.New.Logf(6, "Partial Matcher for %s is %s", path, reAllOps) if resp.EnableCORS { index := len(resp.Svc) if optIndex == nil { optIndex = map[string]int{path: index} } else if index, ok = optIndex[path]; ok { for _, HdrNew = range headers { for _, HdrOld = range resp.Svc[index].Headers { if HdrOld == HdrNew { break } } if HdrOld != HdrNew { resp.Svc[index].Headers = append(resp.Svc[index].Headers, HdrNew) } } continue } else { optIndex[path] = len(resp.Svc) } re = "^OPTIONS" + re[len(httpmethod)+1:] resp.MatchedOps[MatchedOpsIndex] = len(resp.Svc) reComp = regexp.MustCompile(re) MatchedOpsIndex += reComp.NumSubexp() + 1 resp.Svc = append(resp.Svc, UrlNode{ Path: path, Headers: headers, }) reAllOps += "|(" + re + ")" Goose.New.Logf(6, "Partial Matcher with options for %s is %s", path, reAllOps) } } } } Goose.New.Logf(6, "Operations matcher: %s\n", reAllOps[1:]) Goose.New.Logf(6, "Operations %#v\n", resp.Svc) resp.Matcher = regexp.MustCompile(reAllOps[1:]) // Cutting the leading '|' return resp, nil }