2022-06-29 15:25:35 +08:00
|
|
|
// Package rpc ...
|
|
|
|
//
|
|
|
|
// Description : rpc ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 2022-06-29 15:21
|
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
2022-06-30 17:52:09 +08:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2022-06-30 11:42:53 +08:00
|
|
|
"errors"
|
2022-06-30 17:26:19 +08:00
|
|
|
"fmt"
|
2022-06-30 17:52:09 +08:00
|
|
|
"io"
|
2022-06-30 17:41:41 +08:00
|
|
|
"net/http"
|
2022-06-30 17:26:19 +08:00
|
|
|
"strings"
|
2022-06-29 15:25:35 +08:00
|
|
|
"sync"
|
2022-06-30 17:15:22 +08:00
|
|
|
"time"
|
2022-06-29 15:25:35 +08:00
|
|
|
|
2022-06-30 17:41:41 +08:00
|
|
|
"git.zhangdeman.cn/zhangdeman/util"
|
|
|
|
|
2022-06-30 17:26:19 +08:00
|
|
|
"github.com/ddliu/go-httpclient"
|
|
|
|
"github.com/gin-gonic/gin"
|
2022-06-29 15:25:35 +08:00
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
2022-06-29 21:13:45 +08:00
|
|
|
var (
|
|
|
|
// Request 请求实例
|
|
|
|
Request *request
|
|
|
|
)
|
|
|
|
|
2022-06-29 15:25:35 +08:00
|
|
|
// InitRPC 初始化RPC服务
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 15:23 2022/6/29
|
2022-06-30 11:42:53 +08:00
|
|
|
func InitRPC(serviceTable map[string]*Service, loggerInstance *zap.Logger) error {
|
|
|
|
if nil == serviceTable {
|
|
|
|
serviceTable = make(map[string]*Service)
|
|
|
|
}
|
|
|
|
for _, item := range serviceTable {
|
|
|
|
if item.ApiTable == nil {
|
|
|
|
item.ApiTable = make(map[string]*Api)
|
|
|
|
}
|
|
|
|
}
|
2022-06-29 21:13:45 +08:00
|
|
|
Request = &request{
|
2022-06-29 15:25:35 +08:00
|
|
|
logger: loggerInstance,
|
|
|
|
serviceTable: serviceTable,
|
|
|
|
lock: &sync.RWMutex{},
|
|
|
|
}
|
2022-06-29 21:13:45 +08:00
|
|
|
return nil
|
2022-06-29 15:25:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type request struct {
|
|
|
|
logger *zap.Logger
|
2022-06-30 11:42:53 +08:00
|
|
|
serviceTable map[string]*Service
|
2022-06-29 15:25:35 +08:00
|
|
|
lock *sync.RWMutex
|
|
|
|
}
|
2022-06-30 11:42:53 +08:00
|
|
|
|
|
|
|
// AddService 新增一个服务
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 17:13 2022/6/29
|
|
|
|
func (r *request) AddService(serviceInfo *Service) error {
|
|
|
|
if nil == serviceInfo {
|
|
|
|
return errors.New("service info is nil")
|
|
|
|
}
|
|
|
|
r.lock.Lock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
if _, exist := r.serviceTable[serviceInfo.Flag]; exist {
|
|
|
|
return errors.New(serviceInfo.Flag + " already exist")
|
|
|
|
}
|
|
|
|
r.serviceTable[serviceInfo.Flag] = serviceInfo
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetServiceInfo ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 11:32 2022/6/30
|
|
|
|
func (r *request) GetServiceInfo(serviceFlag string) (*Service, error) {
|
|
|
|
var (
|
|
|
|
serviceInfo *Service
|
|
|
|
exist bool
|
|
|
|
)
|
|
|
|
|
|
|
|
r.lock.RLock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
if serviceInfo, exist = r.serviceTable[serviceFlag]; !exist {
|
|
|
|
return nil, errors.New(serviceFlag + " -> 服务不存在")
|
|
|
|
}
|
|
|
|
return serviceInfo, nil
|
|
|
|
}
|
|
|
|
|
2022-06-30 12:05:17 +08:00
|
|
|
// RemoveService 删除一个service
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 11:46 2022/6/30
|
|
|
|
func (r *request) RemoveService(serviceFlag string) {
|
|
|
|
r.lock.Lock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
delete(r.serviceTable, serviceFlag)
|
|
|
|
}
|
|
|
|
|
2022-06-30 11:42:53 +08:00
|
|
|
// AddServiceApi 向一个service中增加Api
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 11:26 2022/6/30
|
|
|
|
func (r *request) AddServiceApi(serviceFlag string, apiConfig *Api) error {
|
|
|
|
var (
|
|
|
|
serviceInfo *Service
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
if serviceInfo, err = r.GetServiceInfo(serviceFlag); nil != err {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.lock.Lock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
if nil == serviceInfo.ApiTable {
|
|
|
|
serviceInfo.ApiTable = make(map[string]*Api)
|
|
|
|
}
|
|
|
|
serviceInfo.ApiTable[apiConfig.Flag] = apiConfig
|
|
|
|
return nil
|
|
|
|
}
|
2022-06-30 12:05:17 +08:00
|
|
|
|
|
|
|
// GetServiceApi 获取服务api配置
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 11:53 2022/6/30
|
|
|
|
func (r *request) GetServiceApi(serviceFlag string, apiFlag string) (*Service, *Api, error) {
|
|
|
|
var (
|
|
|
|
serviceInfo *Service
|
|
|
|
err error
|
|
|
|
exist bool
|
|
|
|
apiInfo *Api
|
|
|
|
)
|
|
|
|
if serviceInfo, err = r.GetServiceInfo(serviceFlag); nil != err {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
r.lock.Lock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
if apiInfo, exist = serviceInfo.ApiTable[apiFlag]; !exist {
|
|
|
|
return nil, nil, errors.New(serviceFlag + " : " + apiFlag + " -> api")
|
|
|
|
}
|
|
|
|
return serviceInfo, apiInfo, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveServiceApi 删除服务下的一个api
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 12:02 2022/6/30
|
|
|
|
func (r *request) RemoveServiceApi(serviceFlag string, apiFlag string) {
|
|
|
|
var (
|
|
|
|
serviceInfo *Service
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
if serviceInfo, _, err = r.GetServiceApi(serviceFlag, apiFlag); nil != err {
|
|
|
|
// 不存在无需处理
|
|
|
|
return
|
|
|
|
}
|
|
|
|
r.lock.Lock()
|
|
|
|
defer r.lock.Unlock()
|
|
|
|
delete(serviceInfo.ApiTable, apiFlag)
|
|
|
|
}
|
2022-06-30 14:25:45 +08:00
|
|
|
|
|
|
|
// Get ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:25 2022/6/30
|
|
|
|
func (r *request) Get() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Post ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:25 2022/6/30
|
|
|
|
func (r *request) Post() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Head ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:25 2022/6/30
|
|
|
|
func (r *request) Head() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Put() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trace ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Trace() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Delete() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Options ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Options() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Patch ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Patch() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
|
|
|
func (r *request) Connect() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send 统一的发送请求方法
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 14:24 2022/6/30
|
2022-06-30 17:26:19 +08:00
|
|
|
func (r *request) Send(ctx *gin.Context, serviceFlag string, apiFlag string, parameter map[string]interface{}, receiver interface{}) error {
|
|
|
|
var (
|
|
|
|
serviceConfig *Service
|
|
|
|
apiConfig *Api
|
|
|
|
err error
|
2022-06-30 17:41:41 +08:00
|
|
|
fullURL string
|
|
|
|
client *httpclient.HttpClient
|
2022-06-30 17:52:09 +08:00
|
|
|
body []byte
|
|
|
|
response *httpclient.Response
|
|
|
|
responseBody []byte
|
2022-06-30 17:26:19 +08:00
|
|
|
)
|
|
|
|
if serviceConfig, apiConfig, err = r.GetServiceApi(serviceFlag, apiFlag); nil != err {
|
|
|
|
return err
|
|
|
|
}
|
2022-06-30 17:41:41 +08:00
|
|
|
// 完整的请求地址
|
2022-06-30 17:52:09 +08:00
|
|
|
fullURL, body = r.getFullURLAndBody(serviceConfig, apiConfig, parameter)
|
|
|
|
if response, err = client.Do(apiConfig.Method, fullURL, apiConfig.Header, bytes.NewReader(body)); nil != err {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if responseBody, err = io.ReadAll(response.Body); nil != err {
|
|
|
|
return err
|
|
|
|
}
|
2022-06-30 14:25:45 +08:00
|
|
|
return nil
|
|
|
|
}
|
2022-06-30 17:15:22 +08:00
|
|
|
|
|
|
|
// GetHttpClient 获取client实例
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 17:00 2022/6/30
|
|
|
|
func (r *request) GetHttpClient(header map[string]string, timeout ApiTimeout) *httpclient.HttpClient {
|
|
|
|
client := httpclient.NewHttpClient()
|
|
|
|
if timeout.Connect <= 0 {
|
|
|
|
timeout.Connect = DefaultConnectTimeout
|
|
|
|
}
|
|
|
|
|
|
|
|
if timeout.Read <= 0 {
|
|
|
|
timeout.Read = DefaultReadTimeout
|
|
|
|
}
|
|
|
|
client.WithHeaders(header)
|
|
|
|
client.WithOption(httpclient.OPT_CONNECTTIMEOUT_MS, time.Duration(timeout.Connect)*time.Millisecond)
|
|
|
|
client.WithOption(httpclient.OPT_TIMEOUT_MS, time.Duration(timeout.Read)*time.Millisecond)
|
|
|
|
return client
|
|
|
|
}
|
2022-06-30 17:26:19 +08:00
|
|
|
|
|
|
|
// getFullURL ...
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 17:23 2022/6/30
|
2022-06-30 17:52:09 +08:00
|
|
|
func (r *request) getFullURLAndBody(serviceConfig *Service, apiConfig *Api, parameter map[string]interface{}) (string, []byte) {
|
2022-06-30 17:26:19 +08:00
|
|
|
fullURL := strings.ReplaceAll(serviceConfig.Domain+"/"+apiConfig.URI, "//", "/")
|
|
|
|
for name, val := range parameter {
|
|
|
|
fullURL = strings.ReplaceAll(fullURL, "{{"+name+"}}", fmt.Sprintf("%v", val))
|
|
|
|
}
|
2022-06-30 17:41:41 +08:00
|
|
|
parameterPair := make([]string, 0)
|
2022-06-30 17:52:09 +08:00
|
|
|
var body []byte
|
2022-06-30 17:41:41 +08:00
|
|
|
switch strings.ToUpper(apiConfig.Method) {
|
|
|
|
case http.MethodGet:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodHead:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodOptions:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodConnect:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodPatch:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodTrace:
|
|
|
|
for name, val := range parameter {
|
|
|
|
var valStr string
|
|
|
|
_ = util.ConvertAssign(&valStr, val)
|
|
|
|
parameterPair = append(parameterPair, fmt.Sprintf("%v=%v", name, valStr))
|
|
|
|
}
|
2022-06-30 17:52:09 +08:00
|
|
|
case http.MethodPost:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodPut:
|
|
|
|
fallthrough
|
|
|
|
case http.MethodDelete:
|
|
|
|
body, _ = json.Marshal(parameter)
|
2022-06-30 17:41:41 +08:00
|
|
|
}
|
|
|
|
query := strings.Join(parameterPair, "&")
|
|
|
|
if len(query) == 0 {
|
2022-06-30 17:52:09 +08:00
|
|
|
return strings.ReplaceAll(fullURL, "//", "/"), body
|
2022-06-30 17:41:41 +08:00
|
|
|
}
|
2022-06-30 17:52:09 +08:00
|
|
|
return strings.ReplaceAll(fullURL, "//", "/") + "?" + query, body
|
2022-06-30 17:26:19 +08:00
|
|
|
}
|