proxy/protocol/dubbo/schema/schema.go (223 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package schema import ( "fmt" "github.com/go-chassis/openlog" "strings" "github.com/go-chassis/go-chassis/v2/core/registry" ) const ( InQuery = 0 InBody = 1 ) //InterfaceSchema is a struct type InterfaceSchema struct { SvcName string JavaClsName string BasePath string Version string AppId string ServiceId string methordArray []DefMethod } //DefMethod is a struct type DefMethod struct { ownerSvc string Path string // 样例: /test/StringArray 需要是包含basepath的URL OperaID string Paras []MethParam //key 参数名称 Verb string // get post ... Responds map[string]*MethRespond //key 为返回码 200 ,404... } //GetRspSchema is a method to get response schema func (this *DefMethod) GetRspSchema(status int) *MethRespond { strStatus := fmt.Sprintf("%d", status) if _, ok := this.Responds[strStatus]; ok { return this.Responds[strStatus] } else { return nil } } //GetParamNameAndWhere is a method to get parameter name func (this *DefMethod) GetParamNameAndWhere(indx int) (string, int) { for _, v := range this.Paras { if v.Indx == indx { //return v.name, v.where if strings.EqualFold(v.Where, "query") { return v.Name, InQuery } else { return v.Name, InBody } } } return "", InQuery } //GetParamSchema is a method to get parameter schema func (this *DefMethod) GetParamSchema(indx int) *MethParam { for _, v := range this.Paras { if v.Indx == indx { return &v } } return nil } //MethRespond is a struct type MethRespond struct { Status string // 200 404... DType string ObjRef DefType } //MethParam is a struct type MethParam struct { Name string //参数名称 Dtype string //参数类型 AdditionalProps map[string]string //附加参数,如果是Dtype是map,则在这里定义value类型 Items map[string]string //当Dtype为array时使用 Required bool //是否必需 Where string //存储位置 query or body Indx int ObjRef DefType } //DefType 契约definitions字段里定义的类型定义 type DefType struct { typeName string dType string JvmClsName string fileds map[string]DefField } //DefField is a struct type DefField struct { dType string formate string } //GetDefTypeFromDef is a function to get defintion type func GetDefTypeFromDef(defs map[string]registry.Definition, ref string) DefType { def := DefType{} names := strings.Split(ref, "/") def.typeName = names[len(names)-1] if sDef, ok := defs[def.typeName]; ok { def.dType = sDef.Types def.JvmClsName = sDef.XJavaClass } return def } //CovertSwaggerMethordToLocalMethord is a function to convert swagger method to local method func CovertSwaggerMethordToLocalMethord(schema *registry.SchemaContent, src *registry.MethodInfo, dst *DefMethod) { dst.OperaID = src.OperationID tmpParas := make([]MethParam, len(src.Parameters)) i := 0 for _, para := range src.Parameters { var defPara MethParam defPara.Name = para.Name if para.Type == "" { if para.Schema.Type != "" { defPara.Dtype = para.Schema.Type } else { defPara.Dtype = "object" if para.Schema.Reference != "" { defPara.ObjRef = GetDefTypeFromDef(schema.Definition, para.Schema.Reference) } } } else { defPara.Dtype = para.Type } defPara.Required = para.Required defPara.Where = para.In defPara.Indx = i tmpParas[i] = defPara i++ } dst.Paras = tmpParas tmpRsps := make(map[string]*MethRespond) for key, rsp := range src.Response { var defRsp MethRespond if dtype, ok := rsp.Schema["type"]; ok { defRsp.DType = dtype } else { defRsp.DType = "object" if dRef, ok := rsp.Schema["$ref"]; ok { defRsp.ObjRef = GetDefTypeFromDef(schema.Definition, dRef) } } defRsp.Status = key tmpRsps[key] = &defRsp } dst.Responds = tmpRsps } //GetSvcByInterface is a function to get service by interface name func GetSvcByInterface(interfaceName string) *registry.MicroService { value, ok := svcToInterfaceCache.Get(interfaceName) if !ok || value == nil { openlog.Info(fmt.Sprintf("Get svc from remote, interface: %s", interfaceName)) svc := registry.DefaultContractDiscoveryService.GetMicroServicesByInterface(interfaceName) if svc != nil { svcKey := strings.Join([]string{svc[0].ServiceName, svc[0].Version, svc[0].AppID}, "/") openlog.Info(fmt.Sprintf("Cached svc [%s] for interface %s", svcKey, interfaceName)) svcToInterfaceCache.Set(interfaceName, svc[0], 0) refresher.Add(newInterfaceJob(interfaceName)) } else { return nil } value, ok = svcToInterfaceCache.Get(interfaceName) } if value != nil { if service, ok2 := value.(*registry.MicroService); ok2 { return service } } return nil } //GetSvcNameByInterface is a function to get service name by interface func GetSvcNameByInterface(interfaceName string) string { svc := registry.DefaultContractDiscoveryService.GetMicroServicesByInterface(interfaceName) for _, v := range svc { return v.ServiceName } return "" } //GetMethodByInterface is a function to get method from interface name func GetMethodByInterface(interfaceName string, operateID string) *DefMethod { var meth DefMethod schema := registry.DefaultContractDiscoveryService.GetSchemaContentByInterface(interfaceName) for path, pathSchema := range schema.Paths { for verb, m := range pathSchema { if strings.EqualFold(m.OperationID, operateID) { meth.Verb = strings.ToUpper(verb) meth.Path = schema.BasePath + path meth.OperaID = operateID CovertSwaggerMethordToLocalMethord(&schema, &m, &meth) return &meth } } } return nil } //GetSchemaMethodBySvcURL is a function to get schema method from URl func GetSchemaMethodBySvcURL(svcName string, env string, ver string, app string, verb string, url string) (*registry.SchemaContent, *DefMethod) { schemas := registry.DefaultContractDiscoveryService.GetSchemaContentByServiceName(svcName, ver, app, env) var curMethrod *DefMethod var curSchema *registry.SchemaContent for _, v := range schemas { curSchema = v methord := GetMethodInfoSchemaByURL(v, verb, url) if methord != nil { if curMethrod == nil { curMethrod = methord } else { if len(curMethrod.Path) < len(methord.Path) { curMethrod = methord } } } } return curSchema, curMethrod } //GetMethodInfoSchemaByURL is a function to get method info schema from URl func GetMethodInfoSchemaByURL(schema *registry.SchemaContent, verb string, url string) *DefMethod { var curMax = 0 basePath := schema.BasePath var method *registry.MethodInfo var path string for key, v := range schema.Paths { if strings.HasPrefix(url, basePath+key) { if tmp, ok := v[verb]; ok { if len(key) > curMax { curMax = len(key) method = &tmp path = key } } } } if method != nil { tmpMeth := &DefMethod{} tmpMeth.Path = basePath + path tmpMeth.Verb = verb CovertSwaggerMethordToLocalMethord(schema, method, tmpMeth) return tmpMeth } else { return nil } }