请求配置验证, 默认值初始化 + full_url + method验证

This commit is contained in:
白茶清欢 2024-05-31 16:39:58 +08:00
parent c977bc0392
commit 2be9c90b79
6 changed files with 293 additions and 12 deletions

90
client.go Normal file
View File

@ -0,0 +1,90 @@
// Package httpclient ...
//
// Description : httpclient ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-05-31 15:22
package httpclient
import (
"git.zhangdeman.cn/gateway/httpclient/define"
"git.zhangdeman.cn/gateway/httpclient/validate"
"github.com/go-resty/resty/v2"
)
// NewHttpClient 获取http client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:27 2024/5/31
func NewHttpClient(reqConfig *define.Request) (*HttpClient, error) {
hc := &HttpClient{
Client: NewRestyClient(reqConfig),
reqConfig: reqConfig,
}
// 验证配置正确性以及初始化默认值
if err := validate.RequestConfig(reqConfig); nil != err {
return nil, err
}
return hc, nil
}
// HttpClient 请求客户端
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:27 2024/5/31
type HttpClient struct {
*resty.Client
reqConfig *define.Request
}
// getRequestValidateMiddleware 请求验证的Middleware
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:40 2024/5/31
func (hc *HttpClient) getRequestValidateMiddleware() resty.RequestMiddleware {
return func(client *resty.Client, request *resty.Request) error {
return nil
}
}
// getResponseValidateMiddleware 获取相应数据验证的middleware
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:42 2024/5/31
func (hc *HttpClient) getResponseValidateMiddleware() resty.ResponseMiddleware {
return func(client *resty.Client, response *resty.Response) error {
return nil
}
}
// SetRestyClient 设置client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:54 2024/5/31
func (hc *HttpClient) SetRestyClient(restyClient *resty.Client) {
hc.Client = restyClient
}
// GetRestyClient 获取 resty client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:57 2024/5/31
func (hc *HttpClient) GetRestyClient() *resty.Client {
return hc.Client
}
// Request 发送请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:52 2024/5/31
func (hc *HttpClient) Request(reqConfig *define.Request) *define.Response {
return nil
}

17
define/error.go Normal file
View File

@ -0,0 +1,17 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-05-31 16:02
package define
import "errors"
var (
ErrRequestConfigNil = errors.New("REQUEST_CONFIG_NIL") // 请求配置 nil
ErrFullUrlEmpty = errors.New("FULL_URL_EMPTY") // 没传 full_url
ErrFullUrlInvalid = errors.New("FULL_URL_Invalid") // 请求 full_url 不是 http 或者 https 开头
ErrMethodIsNotSupport = errors.New("METHOD_IS_NOT_SUPPORT") // 请求 method不支持
)

View File

@ -13,17 +13,20 @@ package define
//
// Date : 17:10 2024/5/24
type Request struct {
Body map[string]any `json:"body"` // 请求Body
Header map[string]string `json:"header"` // 请求Header
Cookie map[string]string `json:"cookie"` // 请求Cookie
Query map[string]string `json:"query"` // 请求query
FullUrl string `json:"full_url"` // 完整的请求URL
ContentType string `json:"content_type"` // 请求类型
Method string `json:"method"` // 请求方法
DataField string `json:"data_field"` // 数据字段
CodeField string `json:"code_field"` // 业务状态码字段
MessageField string `json:"message_field"` // code描述字段
RetryRule *RequestRetryRule `json:"retry_rule"` // 重试规则
Body map[string]any `json:"body"` // 请求Body
Header map[string]string `json:"header"` // 请求Header
Cookie map[string]string `json:"cookie"` // 请求Cookie
Query map[string]string `json:"query"` // 请求query
FullUrl string `json:"full_url"` // 完整的请求URL
ContentType string `json:"content_type"` // 请求类型
Method string `json:"method"` // 请求方法
DataField string `json:"data_field"` // 数据字段
CodeField string `json:"code_field"` // 业务状态码字段
MessageField string `json:"message_field"` // code描述字段
SuccessCodeList []string `json:"success_code_list"` // 哪些业务状态码视为成功
ConnectTimeout int64 `json:"connect_timeout"` // 连接超时时间: ms
ReadTimeout int64 `json:"read_timeout"` // 读取超时时间
RetryRule *RequestRetryRule `json:"retry_rule"` // 重试规则
}
// RequestRetryRule 重试规则
@ -37,3 +40,15 @@ type RequestRetryRule struct {
RetryHttpCodeList []int64 `json:"retry_http_code_list"` // 哪些http状态码需要重试
RetryBusinessCodeList []string `json:"retry_business_code_list"` // 哪些业务状态码需要重试
}
const (
DefaultConnectTimeout = 1000 // 默认连接超时时间
DefaultReadTimeout = 1000 // 默认连接读取时间
DefaultCodeField = "code" // 默认业务状态码字段
DefaultMessageField = "message" // 默认状态码描述字段
DefaultDataField = "data" // 默认数据字段
)
var (
DefaultSuccessCodeList = []string{"0"} // 默认成功业务状态码
)

3
go.mod
View File

@ -2,6 +2,8 @@ module git.zhangdeman.cn/gateway/httpclient
go 1.22.3
require github.com/go-resty/resty/v2 v2.13.1
require (
git.zhangdeman.cn/gateway/validator v0.0.0-20240517061043-10dc8547cc14 // indirect
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240517060653-203cc568fbec // indirect
@ -13,7 +15,6 @@ require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-resty/resty/v2 v2.13.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect

44
resty.go Normal file
View File

@ -0,0 +1,44 @@
// Package httpclient ...
//
// Description : httpclient ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-05-31 14:59
package httpclient
import (
"git.zhangdeman.cn/gateway/httpclient/define"
"github.com/go-resty/resty/v2"
"net/textproto"
)
// NewRestyClient 获取resty client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:00 2024/5/31
func NewRestyClient(requestConfig *define.Request) *resty.Client {
formatHeader(requestConfig)
client := resty.New()
if nil == requestConfig {
return client
}
return client
}
// formatHeader 格式化header
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:18 2024/5/31
func formatHeader(requestConfig *define.Request) {
if nil == requestConfig {
return
}
formatHeaderData := make(map[string]string)
for headerName, headerVal := range requestConfig.Header {
formatHeaderData[textproto.CanonicalMIMEHeaderKey(headerName)] = headerVal
}
requestConfig.Header = formatHeaderData
}

114
validate/request_config.go Normal file
View File

@ -0,0 +1,114 @@
// Package validate ...
//
// Description : validate ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-05-31 16:18
package validate
import (
"git.zhangdeman.cn/gateway/httpclient/define"
"net/http"
"strings"
)
// RequestConfig 验证请求配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:18 2024/5/31
func RequestConfig(reqConfig *define.Request) error {
if nil == reqConfig {
return define.ErrRequestConfigNil
}
rc := &requestConfig{}
if err := rc.validateFullUrl(reqConfig); nil != err {
return err
}
return nil
}
type requestConfig struct {
}
// initDefaultConfig 初始化默认配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:25 2024/5/31
func (rc *requestConfig) initDefaultConfig(reqConfig *define.Request) {
if reqConfig.ConnectTimeout <= 0 {
reqConfig.ConnectTimeout = define.DefaultConnectTimeout
}
if reqConfig.ReadTimeout <= 0 {
reqConfig.ReadTimeout = define.DefaultReadTimeout
}
reqConfig.CodeField = strings.TrimSpace(reqConfig.CodeField)
reqConfig.MessageField = strings.TrimSpace(reqConfig.MessageField)
reqConfig.DataField = strings.TrimSpace(reqConfig.DataField)
if len(reqConfig.CodeField) == 0 {
reqConfig.CodeField = define.DefaultCodeField
}
if len(reqConfig.MessageField) == 0 {
reqConfig.MessageField = define.DefaultMessageField
}
if len(reqConfig.DataField) == 0 {
reqConfig.DataField = define.DefaultDataField
}
if len(reqConfig.SuccessCodeList) == 0 {
reqConfig.SuccessCodeList = define.DefaultSuccessCodeList
}
}
// validateFullUrl 验证full url
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:17 2024/5/31
func (rc *requestConfig) validateFullUrl(reqConfig *define.Request) error {
// 验证 full url
reqConfig.FullUrl = strings.TrimSpace(reqConfig.FullUrl)
if len(reqConfig.FullUrl) == 0 {
return define.ErrFullUrlEmpty
}
if !strings.HasPrefix(reqConfig.FullUrl, "http://") && !strings.HasPrefix(reqConfig.FullUrl, "https://") {
return define.ErrFullUrlInvalid
}
return nil
}
// validateMethod 验证method
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:22 2024/5/31
func (rc *requestConfig) validateMethod(reqConfig *define.Request) error {
// 验证Method
reqConfig.Method = strings.ToUpper(reqConfig.Method)
if len(reqConfig.Method) == 0 {
return define.ErrFullUrlEmpty
}
supportMethodList := []string{
http.MethodGet,
http.MethodHead,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodConnect,
http.MethodOptions,
http.MethodTrace,
}
isSupportMethod := false
for _, item := range supportMethodList {
if item == reqConfig.Method {
isSupportMethod = true
break
}
}
if !isSupportMethod {
return define.ErrMethodIsNotSupport
}
return nil
}