| /* |
| * 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" |
| "strings" |
| |
| "github.com/go-chassis/go-chassis/core/lager" |
| "github.com/go-chassis/go-chassis/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 { |
| lager.Logger.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}, "/") |
| lager.Logger.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 |
| } |
| } |