RPC增加数据mock能力

This commit is contained in:
白茶清欢 2022-10-14 14:54:20 +08:00
parent cc32decb80
commit b6aaa49ab6
5 changed files with 87 additions and 35 deletions

View File

@ -16,6 +16,8 @@ type Service struct {
Flag string `json:"flag" yaml:"flag" ini:"flag"` // 服务标识, 全局唯一
Description string `json:"description" yaml:"description" ini:"description"` // 服务描述
Domain string `json:"domain" yaml:"domain" ini:"domain"` // 域名服务
MockEnable bool `json:"mock_enable" yaml:"mock_enable" ini:"mock_enable"` // 是否可用mock,默认false
MockPath string `json:"mock_path" yaml:"mock_path" ini:"mock_path"` // mock数据的存储路径,不配置默认为 ./{service_flag}
CodeField string `json:"code_field" yaml:"code_field" ini:"code_field"` // 状态码字段
MessageField string `json:"message_field" yaml:"message_field" ini:"message_field"` // 消息字段
DataField string `json:"data_field" yaml:"data_field" ini:"data_field"` // 数据字段
@ -32,6 +34,7 @@ type Service struct {
// Date : 14:18 2022/6/29
type Api struct {
Flag string `json:"flag" yaml:"flag" ini:"flag"` // URI标识
MockEnable bool `json:"mock_enable" yaml:"mock_enable" ini:"mock_enable"` // 当前接口是否可用mock服务
Description string `json:"description" yaml:"description" ini:"description"` // 接口描述
URI string `json:"uri" yaml:"uri" ini:"uri"` // 接口地址
Method string `json:"method" yaml:"method" ini:"method"` // 请求方法 GET / POST / PUT 等

View File

@ -1,6 +1,8 @@
flag: goproxy
description: "包下载信息统计服务"
domain: https://goproxy.cn/
mock_enable: false
mock_path:
code_field: '-'
message_field: '-'
data_field: '-'

2
go.mod
View File

@ -3,7 +3,7 @@ module git.zhangdeman.cn/zhangdeman/rpc
go 1.17
require (
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221010125206-1c9c8be53c82
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221014054633-9931590d801d
github.com/ddliu/go-httpclient v0.6.9
github.com/gin-gonic/gin v1.8.1
github.com/tidwall/gjson v1.14.3

4
go.sum
View File

@ -2,6 +2,10 @@ git.zhangdeman.cn/zhangdeman/util v0.0.0-20220702052429-b5ae4cf80989 h1:2yuM4QDf
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220702052429-b5ae4cf80989/go.mod h1:aQsgOqtMnnwG2n7T/0a1OkYigqBzZivv8Ea6683bK2M=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221010125206-1c9c8be53c82 h1:N9s9fAFWzFNrq7GPdcW8hSG1quRw3S/w+ypwe+nG8xo=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221010125206-1c9c8be53c82/go.mod h1:zTir/0IWdK3E7n0GiaogyWHADAQnBtTdl2I6Z2/OPqw=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221014045307-63f5b99d40dd h1:GAmABFJI1dCZFmxMCW7Jv3LZ+QLys9GNQxNiVGWCEDM=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221014045307-63f5b99d40dd/go.mod h1:zTir/0IWdK3E7n0GiaogyWHADAQnBtTdl2I6Z2/OPqw=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221014054633-9931590d801d h1:JH8+12c4ZPcR1Wsvdwz7OvAw+BrAvMXV1AGf1M1DJ4Y=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221014054633-9931590d801d/go.mod h1:zTir/0IWdK3E7n0GiaogyWHADAQnBtTdl2I6Z2/OPqw=
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=

111
rpc.go
View File

@ -14,7 +14,9 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
@ -73,6 +75,10 @@ func InitRPCFromCfgDir(cfgDir string, logger *zap.Logger) error {
if err = util.File.ReadAnyFileContent(filepathNames[i], &serviceInfo); nil != err {
return err
}
if len(serviceInfo.MockPath) == 0 {
// 填充默认的mock数据存储路径
serviceInfo.MockPath = util.Project.BuildPath("mock")
}
serviceTable[serviceInfo.Flag] = &serviceInfo
}
return InitRPC(serviceTable, logger)
@ -268,6 +274,7 @@ func (r *request) Send(ctx *gin.Context, serviceFlag string, apiFlag string, par
response *httpclient.Response
responseBody []byte
code, message, data string
mockFilePath string
)
// 日志数据
@ -284,48 +291,60 @@ func (r *request) Send(ctx *gin.Context, serviceFlag string, apiFlag string, par
logDataList = append(logDataList, zap.Any("read_api_config_fail", err.Error()))
return err
}
logDataList = append(logDataList, zap.Any("api_config", apiConfig))
logDataList = append(logDataList,
zap.Any("api_config", apiConfig),
zap.Any("service_mock_enable", serviceConfig.MockEnable),
zap.Any("api_mock_enable", apiConfig.MockEnable),
)
// 完整的请求地址
fullURL, body = r.getFullURLAndBody(serviceConfig, apiConfig, parameter)
if responseBody, mockFilePath, err = r.getMockData(serviceConfig, apiConfig); nil == err {
logDataList = append(logDataList, zap.Any("mock_file_path", mockFilePath))
} else {
logDataList = append(logDataList,
zap.Any("mock_file_path", mockFilePath),
zap.Any("mock_disable_reason", err.Error()),
)
// 完整的请求地址
fullURL, body = r.getFullURLAndBody(serviceConfig, apiConfig, parameter)
logDataList = append(logDataList, zap.String("full_utl", fullURL))
fullHeader := make(map[string]string)
for k, v := range apiConfig.Header {
fullHeader[k] = v
}
for k, v := range header {
fullHeader[k] = v
}
// 获取客户端
client = r.GetHttpClient(fullHeader, apiConfig.Timeout)
var bodyReader io.Reader
if nil != body {
logDataList = append(logDataList, zap.String("request_body", string(body)))
bodyReader = bytes.NewReader(body)
}
logDataList = append(logDataList, zap.String("full_utl", fullURL))
fullHeader := make(map[string]string)
for k, v := range apiConfig.Header {
fullHeader[k] = v
}
for k, v := range header {
fullHeader[k] = v
}
// 获取客户端
client = r.GetHttpClient(fullHeader, apiConfig.Timeout)
var bodyReader io.Reader
if nil != body {
logDataList = append(logDataList, zap.String("request_body", string(body)))
bodyReader = bytes.NewReader(body)
}
requestStartTime := time.Now().UnixNano() / 1e6
requestFinishTime := int64(0)
requestStartTime := time.Now().UnixNano() / 1e6
requestFinishTime := int64(0)
logDataList = append(logDataList, zap.Int64("start_time", requestStartTime))
if response, err = client.Do(apiConfig.Method, fullURL, apiConfig.Header, bodyReader); nil != err {
requestFinishTime = time.Now().UnixNano() / 1e6
logDataList = append(logDataList, zap.Int64("finish_time", requestFinishTime))
logDataList = append(logDataList, zap.Int64("used_time", requestFinishTime-requestStartTime))
logDataList = append(logDataList, zap.String("request_fail_reason", err.Error()))
return err
}
logDataList = append(logDataList, zap.Int64("start_time", requestStartTime))
if response, err = client.Do(apiConfig.Method, fullURL, apiConfig.Header, bodyReader); nil != err {
requestFinishTime = time.Now().UnixNano() / 1e6
logDataList = append(logDataList, zap.Int64("finish_time", requestFinishTime))
logDataList = append(logDataList, zap.Int64("used_time", requestFinishTime-requestStartTime))
logDataList = append(logDataList, zap.String("request_fail_reason", err.Error()))
return err
}
logDataList = append(logDataList, zap.Any("response_header", response.Header))
logDataList = append(logDataList, zap.Any("response_http_code", response.StatusCode))
requestFinishTime = time.Now().UnixNano() / 1e6
logDataList = append(logDataList, zap.Int64("finish_time", requestFinishTime))
logDataList = append(logDataList, zap.Int64("used_time", requestFinishTime-requestStartTime))
logDataList = append(logDataList, zap.Any("response_header", response.Header))
logDataList = append(logDataList, zap.Any("response_http_code", response.StatusCode))
if responseBody, err = r.getResponseBody(response); nil != err {
logDataList = append(logDataList, zap.String("read_body_fail_reason", err.Error()))
return err
if responseBody, err = r.getResponseBody(response); nil != err {
logDataList = append(logDataList, zap.String("read_body_fail_reason", err.Error()))
return err
}
}
logDataList = append(logDataList, zap.Any("response_body", string(responseBody)))
@ -352,6 +371,30 @@ func (r *request) Send(ctx *gin.Context, serviceFlag string, apiFlag string, par
return err
}
// getMockData 获取mock数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:29 2022/10/14
func (r *request) getMockData(serviceConfig *Service, apiConfig *Api) ([]byte, string, error) {
mockFilePath := util.Project.BuildPath(serviceConfig.MockPath, serviceConfig.Flag, apiConfig.Flag+".json")
if !serviceConfig.MockEnable || !apiConfig.MockEnable {
// 未启用mock服务
return nil, mockFilePath, errors.New("mock is forbidden")
}
var (
err error
mockData []byte
)
if _, err = os.Stat(mockFilePath); nil != err {
return nil, mockFilePath, errors.New("get mock fileInfo fail : " + err.Error())
}
if mockData, err = ioutil.ReadFile(mockFilePath); nil != err {
return nil, mockFilePath, errors.New("read mock file content fail :" + err.Error())
}
return mockData, mockFilePath, nil
}
// getResponseBody 获取响应体
//
// Author : go_developer@163.com<白茶清欢>