blob: eff96e444b7d37914c520253a6780c678ce90338 [file] [log] [blame]
/*
* 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
}
}