请求配置验证, 默认值初始化 + full_url + method验证
This commit is contained in:
		
							
								
								
									
										90
									
								
								client.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								client.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										17
									
								
								define/error.go
									
									
									
									
									
										Normal 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不支持
 | 
			
		||||
)
 | 
			
		||||
@ -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
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							@ -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
									
								
							
							
						
						
									
										44
									
								
								resty.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										114
									
								
								validate/request_config.go
									
									
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user