Compare commits

..

3 Commits

Author SHA1 Message Date
bb4033d2dc save code 2023-08-01 18:48:36 +08:00
f438b1e0ea 优化获取实例 : gethttpclient 2023-08-01 18:15:20 +08:00
d9051b45d0 迁移代码 2023-08-01 17:37:22 +08:00
16 changed files with 691 additions and 753 deletions

92
curl/define.go Normal file
View File

@ -0,0 +1,92 @@
// Package curl 基础请求库
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 基础常量定义
//
// File: define.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 19:56:48
package curl
import (
"github.com/ddliu/go-httpclient"
)
const (
// ContentTypeFormData form-data 请求
ContentTypeFormData = "form-data"
// ContentTypeFormURLEncoded x-www-form-urlencoded 请求
ContentTypeFormURLEncoded = "application/x-www-form-urlencoded"
// ContentTypeJSON json的请求方式
ContentTypeJSON = "application/json"
// ContentTypeDefault 默认的请求方式
ContentTypeDefault = ContentTypeJSON
)
const (
// BodyTypeJson json数据
BodyTypeJson = "json"
// BodyTypeXML xml数据
BodyTypeXML = "xml"
// BodyTypeYaml yaml数据
BodyTypeYaml = "yaml"
)
const (
// DefaultConnectTimeout 默认连接超时时间, 毫秒
DefaultConnectTimeout = 1000
// DefaultReadTimeout 默认读取超时时间, 毫秒
DefaultReadTimeout = 1000
)
// ApiRequestConfig api请求的配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:14:18
type ApiRequestConfig struct {
Method string `json:"method"` // 请求方法
Domain string `json:"domain"` // 请求域名
URI string `json:"uri"` // 请求的路由
ResponseCodeField string `json:"response_code_field"` // 业务状态码字段
ResponseMessageField string `json:"response_message_field"` // 业务状态码描述的字段
ResponseDataField string `json:"response_data_field"` // 业务数据的字段
SuccessCodeList []string `json:"success_code_list"` // 代表请求成功的code列表
SuccessHttpCodeList []string `json:"success_http_code_list"` // 代表成功的http code列表
Parameter map[string]interface{} `json:"parameter"` // 传入的请求参数
CommonHeader map[string]string `json:"common_header"` // 全部请求都要传的header
Body []byte `json:"-"` // 请求体
FullURL string `json:"full_url"` // 完整请求地址
Timeout Timeout `json:"timeout"` // 超时配置
ContentType string `json:"content_type"` // 请求方法
}
// Timeout 超时配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:02 2022/5/2
type Timeout struct {
Connect int `json:"connect"` // 连接超时
Read int `json:"read"` // 读取超时时间
}
// ApiResponse 接口响应结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:25:39
type ApiResponse struct {
RequestConfig *ApiRequestConfig `json:"request_config"` // 请求配置
Response *httpclient.Response `json:"response"` // 响应体
Exception *Exception `json:"exception"` // 异常信息
StartRequestTime int64 `json:"start_request_time"` // 开始请求时间, 纳秒
FinishRequestTime int64 `json:"finish_request_time"` // 完成请求时间,纳秒
}

76
curl/exception.go Normal file
View File

@ -0,0 +1,76 @@
// Package curl ...
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 定义异常
//
// File: exception.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 20:40:08
package curl
import "strings"
// Exception 定义异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Description: 对于各种异常的描述
//
// Date: 2022/05/01 20:48:21
type Exception struct {
Code string `json:"code"` // 异常的标识码
Message string `json:"message"` // 异常的描述
}
const (
// BindRouterParamNotFound 绑定到路由的参数不存在
BindRouterParamNotFound = "404001"
// ResponseCodeNotFound 响应结果获取不到状态码字段
ResponseCodeNotFound = "404002"
// ResponseMessageNotFound 响应结果获取不到状态码描述字段
ResponseMessageNotFound = "404003"
// ResponseDataNotFound 响应结果获取不到数据字段
ResponseDataNotFound = "404004"
// DomainInvalid 域名设置错误, 必须是 http:// 或者 https:// 开头
DomainInvalid = "400001"
// SendRequestError 请求发送出现异常
SendRequestError = "400002"
// RequestMethodNotSupport 请求方法不支持
RequestMethodNotSupport = "405001"
)
// exceptionTable ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Description: 异常信息表
//
// Date: 2022/05/01 21:02:55
var exceptionTable = map[string]string{
BindRouterParamNotFound: "绑定到路由的参数{{bind_router_param}}不存在, 请确认参数配置",
ResponseCodeNotFound: "基于配置无法获取响应体状态码, 请检查 response_code_field 的配置, 当前配置 {response_code_field}",
ResponseMessageNotFound: "基于配置无法获取响应体状态码, 请检查 response_code_message 的配置, 当前配置 {response_code_message}",
ResponseDataNotFound: "基于配置无法获取响应体状态码, 请检查 {response_code_data} 的配置, 当前配置 {response_code_data}",
DomainInvalid: "api域名配置非法, 必须以 http:// 或者 https:// 开头, 当前配置 {domain}",
RequestMethodNotSupport: "当前请求方法 {method} 不支持, 请核对相关配置",
SendRequestError: "请求发送出现异常, 异常原因 : {real_reason}",
}
// NewException 实力化异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:02:07
func NewException(code string, exceptionData map[string]string) *Exception {
mes := exceptionTable[code]
for k, v := range exceptionData {
mes = strings.ReplaceAll(mes, "{"+k+"}", v)
}
return &Exception{
Code: code,
Message: mes,
}
}

View File

@ -1,4 +1,4 @@
// Package httpclient ... // Package curl ...
// //
// Author: go_developer@163.com<白茶清欢> // Author: go_developer@163.com<白茶清欢>
// //
@ -9,21 +9,16 @@
// Version: 1.0.0 // Version: 1.0.0
// //
// Date: 2022/05/01 21:25:03 // Date: 2022/05/01 21:25:03
package httpclient package curl
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"strings" "strings"
"time" "time"
"git.zhangdeman.cn/zhangdeman/exception"
"github.com/tidwall/gjson"
"github.com/ddliu/go-httpclient" "github.com/ddliu/go-httpclient"
) )
@ -54,7 +49,7 @@ func Request(apiConfig *ApiRequestConfig, header map[string]string, param map[st
default: default:
return &ApiResponse{ return &ApiResponse{
RequestConfig: apiConfig, RequestConfig: apiConfig,
Exception: exception.New(RequestMethodNotSupport, 0, map[string]string{"method": apiConfig.Method}, apiConfig.Method+" : request method is not support"), Exception: NewException(RequestMethodNotSupport, map[string]string{"method": apiConfig.Method}),
Response: nil, Response: nil,
StartRequestTime: time.Now().UnixNano(), StartRequestTime: time.Now().UnixNano(),
FinishRequestTime: time.Now().UnixNano(), FinishRequestTime: time.Now().UnixNano(),
@ -223,40 +218,16 @@ func buildRequestURLAndParam(apiConfig *ApiRequestConfig, header map[string]stri
// Date : 14:53 2022/5/2 // Date : 14:53 2022/5/2
func send(apiConfig *ApiRequestConfig, header map[string]string) *ApiResponse { func send(apiConfig *ApiRequestConfig, header map[string]string) *ApiResponse {
var ( var (
client *httpclient.HttpClient client *httpclient.HttpClient
err error err error
responseByte []byte
) )
// 填充默认配置
if len(apiConfig.ResponseCodeFieldLocation) == 0 {
apiConfig.ResponseCodeFieldLocation = ResponseCodeFieldLocationDefault
}
if len(apiConfig.ResponseCodeField) == 0 {
apiConfig.ResponseCodeField = DefaultResponseCodeField
}
if len(apiConfig.ResponseMessageField) == 0 {
apiConfig.ResponseMessageField = DefaultResponseMessageField
}
if len(apiConfig.ResponseDataField) == 0 {
apiConfig.ResponseDataField = DefaultResponseDataField
}
if len(apiConfig.SuccessCodeList) == 0 {
apiConfig.SuccessCodeList = DefaultSuccessCode
}
if len(apiConfig.SuccessHttpCodeList) == 0 {
apiConfig.SuccessHttpCodeList = DefaultSuccessHttpCode
}
response := &ApiResponse{ response := &ApiResponse{
RequestConfig: apiConfig, RequestConfig: apiConfig,
Response: nil, Response: nil,
Exception: nil, Exception: nil,
StartRequestTime: time.Now().UnixNano(), StartRequestTime: time.Now().UnixNano(),
FinishRequestTime: 0, FinishRequestTime: 0,
Code: "",
Message: "",
Data: "",
} }
defer func() { defer func() {
@ -265,86 +236,7 @@ func send(apiConfig *ApiRequestConfig, header map[string]string) *ApiResponse {
client = getHttpClient(apiConfig, header) client = getHttpClient(apiConfig, header)
if response.Response, err = client.Do(apiConfig.Method, apiConfig.FullURL, nil, bytes.NewReader(apiConfig.Body)); nil != err { if response.Response, err = client.Do(apiConfig.Method, apiConfig.FullURL, nil, bytes.NewReader(apiConfig.Body)); nil != err {
response.Exception = exception.New(SendRequestError, 0, map[string]string{"real_reason": err.Error()}, "http request send fail : "+err.Error()) response.Exception = NewException(SendRequestError, map[string]string{"real_reason": err.Error()})
return response
} }
if responseByte, err = io.ReadAll(response.Response.Body); nil != err {
response.Exception = exception.New(ReadResponseBodyError, response.Response.StatusCode, map[string]string{"real_reason": err.Error()}, "response body read fail : "+err.Error())
return response
}
// 判断http状态码是否为成功
isHttpSuccess := false
responseHttpCode := fmt.Sprintf("%v", response.Response.StatusCode)
for _, itemSuccessHttpCode := range response.RequestConfig.SuccessHttpCodeList {
if responseHttpCode == itemSuccessHttpCode {
isHttpSuccess = true
break
}
}
// http请求失败
if !isHttpSuccess {
response.Exception = exception.New(ResponseHttpCodeIsNotSuccess, response.Response.StatusCode, map[string]string{
"real_reason": responseHttpCode + " : response http code is not success",
}, responseHttpCode+" : response http code is not success")
return response
}
// 提取响应错误码
if response.RequestConfig.ResponseCodeFieldLocation == ResponseCodeFieldLocationHeader {
if strings.ToLower(response.RequestConfig.ResponseCodeField) == "http_code" {
response.Code = responseHttpCode
} else {
response.Code = response.Response.Header.Get(response.RequestConfig.ResponseCodeField)
}
} else {
businessCode := gjson.GetBytes(responseByte, response.RequestConfig.ResponseCodeField)
if businessCode.Exists() {
response.Code = businessCode.String()
}
}
// 判断是否提取到响应状态码
if len(response.Code) == 0 {
response.Exception = exception.New(ResponseCodeNotFound, response.Response.StatusCode, map[string]string{
"real_reason": "parse response business code fail",
}, fmt.Sprintf("business code location : %v, business code name : %v, parse business code fail", response.RequestConfig.ResponseCodeFieldLocation, response.RequestConfig.ResponseCodeField))
return response
}
// 提取响应文案
response.Message = gjson.GetBytes(responseByte, response.RequestConfig.ResponseMessageField).String()
// 判断响应状态码是否成功
isBusinessCodeSuccess := false
for _, itemSuccessCode := range response.RequestConfig.SuccessCodeList {
if itemSuccessCode == response.Code {
isBusinessCodeSuccess = true
break
}
}
if len(response.Message) == 0 {
if isBusinessCodeSuccess {
response.Message = DefaultSuccessMessage
} else {
response.Message = DefaultFailMessage
}
}
if !isBusinessCodeSuccess {
response.Exception = exception.New(ResponseCodeNotFound, response.Response.StatusCode, map[string]string{}, response.Message)
return response
}
// 提取响应数据
if response.RequestConfig.ResponseDataField == ResponseBodyAsData {
response.Data = string(responseByte)
} else {
responseData := gjson.GetBytes(responseByte, response.RequestConfig.ResponseDataField)
if !responseData.Exists() {
response.Exception = exception.New(ResponseDataNotFound, response.Response.StatusCode, map[string]string{}, "response data not found, data field name : "+response.RequestConfig.ResponseDataField)
return response
}
response.Data = responseData.String()
}
return response return response
} }

88
define.go Normal file
View File

@ -0,0 +1,88 @@
// Package httpclient 基础请求库
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 基础常量定义
//
// File: define.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 19:56:48
package httpclient
const (
// ContentTypeFormData form-data 请求
ContentTypeFormData = "form-data"
// ContentTypeFormURLEncoded x-www-form-urlencoded 请求
ContentTypeFormURLEncoded = "application/x-www-form-urlencoded"
// ContentTypeJSON json的请求方式
ContentTypeJSON = "application/json"
// ContentTypeDefault 默认的请求方式
ContentTypeDefault = ContentTypeJSON
)
const (
// BodyTypeJson json数据
BodyTypeJson = "json"
// BodyTypeXML xml数据
BodyTypeXML = "xml"
// BodyTypeYaml yaml数据
BodyTypeYaml = "yaml"
)
const (
// DefaultConnectTimeout 默认连接超时时间, 毫秒
DefaultConnectTimeout = 1000
// DefaultReadTimeout 默认读取超时时间, 毫秒
DefaultReadTimeout = 1000
)
// ApiRequestConfig api请求的配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:14:18
type ApiRequestConfig struct {
Method string `json:"method"` // 请求方法
Domain string `json:"domain"` // 请求域名
URI string `json:"uri"` // 请求的路由
ResponseCodeField string `json:"response_code_field"` // 业务状态码字段
ResponseMessageField string `json:"response_message_field"` // 业务状态码描述的字段
ResponseDataField string `json:"response_data_field"` // 业务数据的字段
SuccessCodeList []string `json:"success_code_list"` // 代表请求成功的code列表
SuccessHttpCodeList []string `json:"success_http_code_list"` // 代表成功的http code列表
Parameter map[string]interface{} `json:"parameter"` // 传入的请求参数
CommonHeader map[string]string `json:"common_header"` // 全部请求都要传的header
Body []byte `json:"-"` // 请求体
FullURL string `json:"full_url"` // 完整请求地址
Timeout Timeout `json:"timeout"` // 超时配置
ContentType string `json:"content_type"` // 请求方法
}
// Timeout 超时配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:02 2022/5/2
type Timeout struct {
Connect int `json:"connect"` // 连接超时
Read int `json:"read"` // 读取超时时间
}
// ApiResponse 接口响应结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:25:39
type ApiResponse struct {
RequestConfig *ApiRequestConfig `json:"request_config"` // 请求配置
Response map[string]interface{} `json:"response"` // 响应体
Exception *Exception `json:"exception"` // 异常信息
StartRequestTime int64 `json:"start_request_time"` // 开始请求时间, 纳秒
FinishRequestTime int64 `json:"finish_request_time"` // 完成请求时间,纳秒
}

76
exception.go Normal file
View File

@ -0,0 +1,76 @@
// Package httpclient ...
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 定义异常
//
// File: exception.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 20:40:08
package httpclient
import "strings"
// Exception 定义异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Description: 对于各种异常的描述
//
// Date: 2022/05/01 20:48:21
type Exception struct {
Code string `json:"code"` // 异常的标识码
Message string `json:"message"` // 异常的描述
}
const (
// BindRouterParamNotFound 绑定到路由的参数不存在
BindRouterParamNotFound = "404001"
// ResponseCodeNotFound 响应结果获取不到状态码字段
ResponseCodeNotFound = "404002"
// ResponseMessageNotFound 响应结果获取不到状态码描述字段
ResponseMessageNotFound = "404003"
// ResponseDataNotFound 响应结果获取不到数据字段
ResponseDataNotFound = "404004"
// DomainInvalid 域名设置错误, 必须是 http:// 或者 https:// 开头
DomainInvalid = "400001"
// SendRequestError 请求发送出现异常
SendRequestError = "400002"
// RequestMethodNotSupport 请求方法不支持
RequestMethodNotSupport = "405001"
)
// exceptionTable ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Description: 异常信息表
//
// Date: 2022/05/01 21:02:55
var exceptionTable = map[string]string{
BindRouterParamNotFound: "绑定到路由的参数{{bind_router_param}}不存在, 请确认参数配置",
ResponseCodeNotFound: "基于配置无法获取响应体状态码, 请检查 response_code_field 的配置, 当前配置 {response_code_field}",
ResponseMessageNotFound: "基于配置无法获取响应体状态码, 请检查 response_code_message 的配置, 当前配置 {response_code_message}",
ResponseDataNotFound: "基于配置无法获取响应体状态码, 请检查 {response_code_data} 的配置, 当前配置 {response_code_data}",
DomainInvalid: "api域名配置非法, 必须以 http:// 或者 https:// 开头, 当前配置 {domain}",
RequestMethodNotSupport: "当前请求方法 {method} 不支持, 请核对相关配置",
SendRequestError: "请求发送出现异常, 异常原因 : {real_reason}",
}
// NewException 实力化异常
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:02:07
func NewException(code string, exceptionData map[string]string) *Exception {
mes := exceptionTable[code]
for k, v := range exceptionData {
mes = strings.ReplaceAll(mes, "{"+k+"}", v)
}
return &Exception{
Code: code,
Message: mes,
}
}

30
go.mod
View File

@ -1,16 +1,32 @@
module git.zhangdeman.cn/zhangdeman/network module git.zhangdeman.cn/zhangdeman/httpclient
go 1.20 go 1.20
require ( require (
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20230819024237-f674702ad28d
github.com/ddliu/go-httpclient v0.7.1 github.com/ddliu/go-httpclient v0.7.1
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 github.com/guonaihong/gout v0.3.8
github.com/mssola/user_agent v0.6.0
github.com/tidwall/gjson v1.16.0
) )
require ( require (
github.com/tidwall/match v1.1.1 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/tidwall/pretty v1.2.1 // indirect github.com/bytedance/sonic v1.7.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.9 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
) )

100
go.sum
View File

@ -1,17 +1,91 @@
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20230819024237-f674702ad28d h1:XqjAykNMm/ai1+CebqcxBKXmIQqZNyYmTeIufLTXQJc= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20230819024237-f674702ad28d/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.7.0 h1:P7DyGrkLbVDzcuqagPsSFnAwwljjhmB3qVF5wzmHOxE=
github.com/bytedance/sonic v1.7.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ddliu/go-httpclient v0.7.1 h1:COWYBalfbaFNe6e0eQU38++vCD5kzLh1H1RFs3xcn9g= github.com/ddliu/go-httpclient v0.7.1 h1:COWYBalfbaFNe6e0eQU38++vCD5kzLh1H1RFs3xcn9g=
github.com/ddliu/go-httpclient v0.7.1/go.mod h1:uwipe9x9SYGk4JhBemO7+dD87QbiY224y0DLB9OY0Ik= github.com/ddliu/go-httpclient v0.7.1/go.mod h1:uwipe9x9SYGk4JhBemO7+dD87QbiY224y0DLB9OY0Ik=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/guonaihong/gout v0.3.8 h1:t0yjR0DgwVX6L4Zf/gv7ZVUcVPMicEpnnWjk3XxFTKA=
github.com/guonaihong/gout v0.3.8/go.mod h1:wDXeuyeZR6MtaHbytO9RLcKW4iCDrWD6/KF1QwDtbRc=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -1,125 +0,0 @@
// Package httpclient 基础请求库
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 基础常量定义
//
// File: define.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 19:56:48
package httpclient
import (
"git.zhangdeman.cn/zhangdeman/exception"
"github.com/ddliu/go-httpclient"
)
const (
// ContentTypeFormData form-data 请求
ContentTypeFormData = "form-data"
// ContentTypeFormURLEncoded x-www-form-urlencoded 请求
ContentTypeFormURLEncoded = "application/x-www-form-urlencoded"
// ContentTypeJSON json的请求方式
ContentTypeJSON = "application/json"
// ContentTypeDefault 默认的请求方式
ContentTypeDefault = ContentTypeJSON
)
const (
// BodyTypeJson json数据
BodyTypeJson = "json"
// BodyTypeXML xml数据
BodyTypeXML = "xml"
// BodyTypeYaml yaml数据
BodyTypeYaml = "yaml"
)
const (
// DefaultConnectTimeout 默认连接超时时间, 毫秒
DefaultConnectTimeout = 1000
// DefaultReadTimeout 默认读取超时时间, 毫秒
DefaultReadTimeout = 1000
// DefaultResponseCodeField 默认code字段
DefaultResponseCodeField = "code"
// DefaultResponseMessageField 默认message字段
DefaultResponseMessageField = "message"
// DefaultResponseDataField 默认数据字段
DefaultResponseDataField = "data"
// DefaultFailMessage 接口响应失败
DefaultFailMessage = "api request fail"
// DefaultSuccessMessage 接口响应成功
DefaultSuccessMessage = "api request success"
)
var (
// DefaultSuccessCode 默认成功状态码
DefaultSuccessCode = []string{"0", "200"}
// DefaultSuccessHttpCode 默认成功http状态码
DefaultSuccessHttpCode = []string{"200"}
)
const (
// ResponseCodeFieldLocationBody 响应状态码在body
ResponseCodeFieldLocationBody = "body"
// ResponseCodeFieldLocationHeader 在header
ResponseCodeFieldLocationHeader = "header"
// ResponseCodeFieldLocationDefault 响应状态码位置默认值
ResponseCodeFieldLocationDefault = ResponseCodeFieldLocationBody
// ResponseBodyAsData 会用整体的body作为数据
ResponseBodyAsData = "__response__body__"
)
// ApiRequestConfig api请求的配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:14:18
type ApiRequestConfig struct {
Method string `json:"method"` // 请求方法
Domain string `json:"domain"` // 请求域名
URI string `json:"uri"` // 请求的路由
ResponseCodeField string `json:"response_code_field"` // 业务状态码字段
ResponseCodeFieldLocation string `json:"response_code_field_location"` // 响应的业务状态码位置, 默认 : body . 可配置 body / header
ResponseMessageField string `json:"response_message_field"` // 业务状态码描述的字段
ResponseDataField string `json:"response_data_field"` // 业务数据的字段
SuccessCodeList []string `json:"success_code_list"` // 代表请求成功的code列表
SuccessHttpCodeList []string `json:"success_http_code_list"` // 代表成功的http code列表
Parameter map[string]interface{} `json:"parameter"` // 传入的请求参数
CommonHeader map[string]string `json:"common_header"` // 全部请求都要传的header
Body []byte `json:"-"` // 请求体
FullURL string `json:"full_url"` // 完整请求地址
Timeout Timeout `json:"timeout"` // 超时配置
ContentType string `json:"content_type"` // 请求方法
}
// Timeout 超时配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:02 2022/5/2
type Timeout struct {
Connect int `json:"connect"` // 连接超时
Read int `json:"read"` // 读取超时时间
}
// ApiResponse 接口响应结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Description:
//
// Date: 2022/05/01 20:25:39
type ApiResponse struct {
RequestConfig *ApiRequestConfig `json:"request_config"` // 请求配置
Response *httpclient.Response `json:"response"` // 响应体
Exception exception.IException `json:"-"` // 异常信息
StartRequestTime int64 `json:"start_request_time"` // 开始请求时间, 纳秒
FinishRequestTime int64 `json:"finish_request_time"` // 完成请求时间,纳秒
Code string `json:"code"` // 业务状态码
Message string `json:"message"` // 状态码描述
Data string `json:"data"` // 响应数据
}

View File

@ -1,27 +0,0 @@
// Package httpclient ...
//
// Author: go_developer@163.com<白茶清欢>
//
// Description: 定义异常
//
// File: exception.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 20:40:08
package httpclient
const (
// ResponseCodeNotFound 响应结果获取不到状态码字段
ResponseCodeNotFound = 404000000002
// ResponseDataNotFound 响应结果获取不到数据字段
ResponseDataNotFound = 404000000004
// SendRequestError 请求发送出现异常
SendRequestError = 400000000002
// ReadResponseBodyError 读取响应数据体出现异常
ReadResponseBodyError = 400000000003
// RequestMethodNotSupport 请求方法不支持
RequestMethodNotSupport = 405000000001
// ResponseHttpCodeIsNotSuccess 响应的http状态码非成功
ResponseHttpCodeIsNotSuccess = 500000000001
)

243
request.go Normal file
View File

@ -0,0 +1,243 @@
// Package httpclient ...
//
// Author: go_developer@163.com<白茶清欢>
//
// Description:
//
// File: request.go
//
// Version: 1.0.0
//
// Date: 2022/05/01 21:25:03
package httpclient
import (
"encoding/json"
"fmt"
"github.com/guonaihong/gout/dataflow"
"net/http"
"strings"
"time"
"github.com/guonaihong/gout"
)
// Request 发送请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:26:02
func Request(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = strings.ToUpper(apiConfig.Method)
switch apiConfig.Method {
case http.MethodGet:
return GET(apiConfig, header, param)
case http.MethodPost:
return POST(apiConfig, header, param)
case http.MethodPut:
return PUT(apiConfig, header, param)
case http.MethodDelete:
return DELETE(apiConfig, header, param)
case http.MethodConnect:
return Connect(apiConfig, header, param)
case http.MethodOptions:
return OPTION(apiConfig, header, param)
case http.MethodTrace:
return Trace(apiConfig, header, param)
case http.MethodPatch:
return Patch(apiConfig, header, param)
default:
return &ApiResponse{
RequestConfig: apiConfig,
Exception: NewException(RequestMethodNotSupport, map[string]string{"method": apiConfig.Method}),
Response: nil,
StartRequestTime: time.Now().UnixNano(),
FinishRequestTime: time.Now().UnixNano(),
}
}
}
// GET ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date: 2022/05/01 21:29:09
func GET(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodGet
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// POST post请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:31:36
func POST(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodPost
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// PUT put请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:31:52
func PUT(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodPut
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// DELETE delete请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:32:08
func DELETE(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodDelete
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// OPTION option请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:32:18
func OPTION(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodOptions
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// Patch patch请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:36:12
func Patch(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodPatch
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// Trace trace请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:36:24
func Trace(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodTrace
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// Connect connect请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/05/01 21:36:39
func Connect(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) *ApiResponse {
apiConfig.Method = http.MethodConnect
buildRequestURLAndParam(apiConfig, header, param)
return send(apiConfig, header)
}
// getHttpClient 获取httpclient实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:27 2022/5/1
func getHttpClient(apiConfig *ApiRequestConfig, header map[string]string) *dataflow.DataFlow {
fullHeader := make(map[string]string)
for name, val := range apiConfig.CommonHeader {
fullHeader[name] = val
}
for name, val := range header {
fullHeader[name] = val
}
if len(apiConfig.ContentType) == 0 {
apiConfig.ContentType = ContentTypeDefault
}
fullHeader["content-type"] = apiConfig.ContentType
return gout.New().SetMethod(apiConfig.Method).
SetHeader(header).
SetTimeout(time.Second * time.Duration(apiConfig.Timeout.Connect+apiConfig.Timeout.Read))
}
// buildRequestURLAndParam 构建完整请求URL与请求参数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:55 2022/5/1
func buildRequestURLAndParam(apiConfig *ApiRequestConfig, header map[string]string, param map[string]interface{}) {
apiConfig.Method = strings.ToUpper(apiConfig.Method)
if apiConfig.Timeout.Connect == 0 {
apiConfig.Timeout.Connect = DefaultConnectTimeout
}
if apiConfig.Timeout.Read == 0 {
apiConfig.Timeout.Read = DefaultConnectTimeout
}
formatParam := make(map[string]interface{})
for paramName, paramValue := range param {
uriTemplate := "{" + paramName + "}"
if strings.Contains(apiConfig.URI, uriTemplate) {
apiConfig.URI = strings.ReplaceAll(apiConfig.URI, uriTemplate, fmt.Sprintf("%v", paramValue))
continue
}
formatParam[paramName] = paramValue
}
apiConfig.Parameter = formatParam
paramPair := make([]string, 0)
switch apiConfig.Method {
case http.MethodPost:
apiConfig.Body, _ = json.Marshal(formatParam)
default:
for paramName, paramValue := range formatParam {
paramPair = append(paramPair, fmt.Sprintf("%v=%v", paramName, paramValue))
}
if len(paramPair) > 0 {
apiConfig.URI = apiConfig.URI + "?" + strings.Join(paramPair, "&")
}
}
if strings.HasSuffix(apiConfig.Domain, "/") {
apiConfig.Domain = strings.TrimRight(apiConfig.Domain, "/")
}
if !strings.HasPrefix(apiConfig.URI, "/") {
apiConfig.URI = "/" + apiConfig.URI
}
apiConfig.FullURL = apiConfig.Domain + apiConfig.URI
}
// send 发送请求
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:53 2022/5/2
func send(apiConfig *ApiRequestConfig, header map[string]string) *ApiResponse {
var (
client *dataflow.DataFlow
err error
)
response := &ApiResponse{
RequestConfig: apiConfig,
Response: nil,
Exception: nil,
StartRequestTime: time.Now().UnixNano(),
FinishRequestTime: 0,
}
defer func() {
response.FinishRequestTime = time.Now().UnixNano()
}()
client = getHttpClient(apiConfig, header)
/*if response.Response, err = client.Do(apiConfig.Method, apiConfig.FullURL, nil, bytes.NewReader(apiConfig.Body)); nil != err {
response.Exception = NewException(SendRequestError, map[string]string{"real_reason": err.Error()})
}*/
return response
}

View File

@ -1,33 +0,0 @@
// Package util ...
//
// Description : util ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-04-09 19:02
package util
import (
"fmt"
"os/exec"
"runtime"
)
type browser struct {
commandTable map[string]string
}
// Open 使用系统默认浏览器打开链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 19:05 2023/4/9
func (b *browser) Open(link string) error {
run, ok := b.commandTable[runtime.GOOS]
if !ok {
return fmt.Errorf("don't know how to open things on %s platform", runtime.GOOS)
}
cmd := exec.Command(run, link)
return cmd.Start()
}

View File

@ -1,36 +0,0 @@
// Package util ...
//
// Description : util ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-08-10 14:34
package util
var (
// UserAgent ...
UserAgent *userAgent
// Browser ...
Browser *browser
// IP ...
IP *ip
// URL ...
URL *ownURL
// JWT ...
JWT *ownJwt
)
func init() {
UserAgent = &userAgent{
list: defaultUserAgentList,
}
Browser = &browser{
commandTable: map[string]string{
"windows": "start",
"darwin": "open",
"linux": "xdg-open",
},
}
IP = &ip{}
URL = &ownURL{}
}

View File

@ -1,59 +0,0 @@
// Package util...
//
// Description : util...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-03-09 5:56 下午
package util
import (
"net"
"net/http"
)
// ip ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:47 2022/5/14
type ip struct {
}
// GetHostIP 获取本机IP地址
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:58 下午 2021/3/9
func (i *ip) GetHostIP() string {
hostIP := "127.0.0.1"
addrs, _ := net.InterfaceAddrs()
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
hostIP = ipnet.IP.String()
break
}
}
}
return hostIP
}
// GetRemoteIP 获取远端IP
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:35 下午 2021/11/22
func (i *ip) GetRemoteIP(req *http.Request) string {
// Try via request
remoteIP, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
return "::1"
}
userIP := net.ParseIP(remoteIP)
if userIP == nil {
return "::1"
}
return userIP.String()
}

View File

@ -1,66 +0,0 @@
// Package util ...
//
// Description : go-jwt具体实现
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-02-11 20:09
package util
import (
"errors"
"github.com/dgrijalva/jwt-go/v4"
)
type ownJwt struct {
}
type MyClaims struct {
jwt.StandardClaims
}
// Generate 生成 token
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:13 2023/2/11
func (j *ownJwt) Generate(signMethod jwt.SigningMethod, secret string, claims jwt.Claims) (string, error) {
if nil == signMethod {
signMethod = jwt.SigningMethodHS256
}
var (
token *jwt.Token
)
if nil == claims {
token = jwt.New(signMethod)
} else {
token = jwt.NewWithClaims(signMethod, claims)
}
return token.SignedString([]byte(secret))
}
// Validate 验证token
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:13 2023/2/11
func (j *ownJwt) Validate(inputToken string, secret string, claims jwt.Claims) (jwt.Claims, error) {
var (
token *jwt.Token
err error
)
if token, err = jwt.ParseWithClaims(inputToken, claims, func(tokenInfo *jwt.Token) (interface{}, error) {
return []byte(secret), nil
}); nil != err {
return nil, errors.New("token parse fail : " + err.Error())
}
if !token.Valid {
return nil, errors.New("token is valid : " + err.Error())
}
return token.Claims, nil
}

View File

@ -1,97 +0,0 @@
// Package util...
//
// Description : util...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-04 2:38 下午
package util
import (
"net/url"
"strings"
)
// URLParseResult url解析
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:51 下午 2021/11/4
type URLParseResult struct {
Scheme string `json:"scheme"`
Domain string `json:"domain"`
URI string `json:"uri"`
Parameter map[string]string `json:"parameter"`
}
// ownURL ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:38 2022/5/14
type ownURL struct {
}
// Encode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func (ou *ownURL) Encode(inputURL string) string {
return url.QueryEscape(inputURL)
}
// Decode ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func (ou *ownURL) Decode(inputURL string) (string, error) {
return url.QueryUnescape(inputURL)
}
// Parse url解析
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:39 下午 2021/11/4
func (ou *ownURL) Parse(inputURL string) (*URLParseResult, error) {
var (
parseResult *url.URL
err error
)
if parseResult, err = url.Parse(inputURL); nil != err {
return nil, err
}
detail := &URLParseResult{
Scheme: parseResult.Scheme,
Domain: parseResult.Host,
URI: parseResult.Path,
Parameter: make(map[string]string),
}
for k, v := range parseResult.Query() {
if len(v) > 1 {
detail.Parameter[k] = "[" + strings.Join(v, ",") + "]"
} else {
detail.Parameter[k] = v[0]
}
}
return detail, nil
}
// BuildQueryURL 构建GET链接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:43 下午 2021/11/4
func (ou *ownURL) BuildQueryURL(apiURL string, parameter map[string]string) string {
u := url.Values{}
for k, v := range parameter {
u.Set(k, v)
}
apiURL = strings.Trim(apiURL, "?")
if strings.Contains(apiURL, "?") {
return apiURL + "&" + u.Encode()
}
return apiURL + "?" + u.Encode()
}

View File

@ -1,176 +0,0 @@
// Package util ...
//
// Description : util ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-03-31 18:51
package util
import (
"math/rand"
"time"
"github.com/mssola/user_agent"
)
var defaultUserAgentList = []string{
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.3 Mobile/14E277 Safari/603.1.30",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1",
"(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11",
"(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6",
"(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6",
"(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1",
"(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5",
"(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5",
"(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3",
"(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24",
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24",
"(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
}
type userAgent struct {
list []string
}
// Set 设置ua池
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:55 2023/3/31
func (ua *userAgent) Set(agentList []string) {
if len(agentList) == 0 {
return
}
ua.list = agentList
}
// GetRandomUA 随机获取UA
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:56 2023/3/31
func (ua *userAgent) GetRandomUA() string {
rand.Seed(time.Now().UnixNano())
idx := rand.Intn(len(ua.list))
return ua.list[idx]
}
// Parse 解析UA
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:31 2023/4/20
func (ua *userAgent) Parse(inputUA string) *UAInfo {
uaInstance := user_agent.New(inputUA)
uaInfo := &UAInfo{
Mozilla: uaInstance.Mozilla(),
Platform: uaInstance.Platform(),
OS: uaInstance.OS(),
Localization: uaInstance.Localization(),
Model: uaInstance.Model(),
Browser: &BrowserInfo{
Engine: "",
EngineVersion: "",
Name: "",
Version: "",
},
OSInfo: &OSInfo{
FullName: uaInstance.OSInfo().FullName,
Name: uaInstance.OSInfo().Name,
Version: uaInstance.OSInfo().Version,
},
Bot: false,
Mobile: false,
Undecided: false,
}
uaInfo.Browser.Engine, uaInfo.Browser.EngineVersion = uaInstance.Engine()
uaInfo.Browser.Name, uaInfo.Browser.Version = uaInstance.Browser()
return uaInfo
}
// UAInfo ua解析结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:34 2023/4/20
type UAInfo struct {
Mozilla string `json:"mozilla"`
Platform string `json:"platform"`
OS string `json:"os"`
OSInfo *OSInfo `json:"os_info"`
Localization string `json:"localization"`
Model string `json:"model"`
Browser *BrowserInfo `json:"browser"`
Bot bool `json:"bot"`
Mobile bool `json:"mobile"`
Undecided bool `json:"undecided"`
}
// BrowserInfo 浏览器信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:34 2023/4/20
type BrowserInfo struct {
Engine string `json:"engine"` // 浏览器引擎
EngineVersion string `json:"engine_version"` // 浏览器引擎版本
Name string `json:"name"` // 浏览器名称
Version string `json:"version"` // 浏览器版本
}
// OSInfo 系统信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:34 2023/4/20
type OSInfo struct {
FullName string `json:"full_name"` // 操作系统全称
Name string `json:"name"` // 操作系统名称
Version string `json:"version"` // 操作系统版本
}