1 Star 0 Fork 0

h79 / gothird

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
api.go 5.94 KB
一键复制 编辑 原始数据 按行查看 历史
huqiuyun 提交于 2024-06-22 18:12 . log http
package token
import (
"bytes"
"errors"
"fmt"
"gitee.com/h79/goutils/common/data"
commonhttp "gitee.com/h79/goutils/common/http"
"gitee.com/h79/goutils/common/logger"
"mime/multipart"
"net/http"
)
type ApiOption func(api *Api)
type apiOption struct {
data data.D
token string
appId string
secret string
seqNo string
tryCount int
debug int
buildUrlFn ApiBuildUrlFunc
setHeadFn ApiSetHeadFunc
setTokenFn ApiSetTokenFunc
getTokenFn ApiGetTokenFunc
}
type Api struct {
token Token
opt apiOption
}
type ApiBuildUrlFunc func(uri string, acsToken string, d data.D) string
type ApiSetHeadFunc func(h *http.Header, acsToken string)
type ApiSetTokenFunc func(appId string, token string)
type ApiGetTokenFunc func(appId string, d data.D) (string, error)
func WithAppendData(src data.D) ApiOption {
return func(api *Api) {
api.opt.data.Append(src)
}
}
func WithSetData(key string, val interface{}) ApiOption {
return func(api *Api) {
api.opt.data[key] = val
}
}
func WithToken(token string) ApiOption {
return func(api *Api) {
api.opt.token = token
}
}
func WithAppId(appId string) ApiOption {
return func(api *Api) {
api.opt.appId = appId
}
}
func WithSecret(secret string) ApiOption {
return func(api *Api) {
api.opt.secret = secret
}
}
func WithDebug() ApiOption {
return func(api *Api) {
api.opt.debug = 1
}
}
func WithSeqNo(no string) ApiOption {
return func(api *Api) {
api.opt.seqNo = no
}
}
func WithTryCount(count int) ApiOption {
return func(api *Api) {
if count > 4 {
count = 4 //最多重试4次
}
api.opt.tryCount = count
}
}
func WithBuildUrl(fn ApiBuildUrlFunc) ApiOption {
return func(api *Api) {
api.opt.buildUrlFn = fn
}
}
func WithHeadFunc(fn ApiSetHeadFunc) ApiOption {
return func(api *Api) {
api.opt.setHeadFn = fn
}
}
func WithSetTokenFunc(fn ApiSetTokenFunc) ApiOption {
return func(api *Api) {
api.opt.setTokenFn = fn
}
}
func WithGetTokenFunc(fn ApiGetTokenFunc) ApiOption {
return func(api *Api) {
api.opt.getTokenFn = fn
}
}
func NewApi(tk Token, opts ...ApiOption) *Api {
a := &Api{token: tk, opt: apiOption{data: data.D{}, token: "", tryCount: 2, buildUrlFn: nil}}
return a.WithOptions(opts...)
}
func (api *Api) Clone() *Api {
return &Api{token: api.token, opt: api.opt}
}
func (api *Api) WithOptions(opts ...ApiOption) *Api {
for i := range opts {
opts[i](api)
}
return api
}
func (api *Api) AppId() string {
if api.opt.appId != "" {
return api.opt.appId
}
if api.token != nil {
return api.token.GetAppId()
}
return ""
}
func (api *Api) IsDebug() bool {
return api.opt.debug == 1
}
func (api *Api) Secret() string {
if api.opt.secret != "" {
return api.opt.secret
}
if api.token != nil {
return api.token.GetSecret()
}
return ""
}
func (api *Api) ResetToken() {
api.setToken("")
if api.token != nil {
api.token.ClearAccessToken()
}
}
func (api *Api) GetAccessToken() (string, error) {
if api.opt.token != "" {
return api.opt.token, nil
}
var err error
var tk string
if api.token != nil {
tk, err = api.token.GetAccessToken(func(options *data.Options) {
options.Data.Append(api.opt.data)
})
} else if api.opt.getTokenFn != nil {
tk, err = api.opt.getTokenFn(api.AppId(), api.opt.data)
} else {
panic("internal error")
}
api.setToken(tk)
return api.opt.token, err
}
func (api *Api) setToken(tk string) {
api.opt.token = tk
if api.opt.setTokenFn != nil {
api.opt.setTokenFn(api.AppId(), api.opt.token)
}
}
type ApiResCallBack func(hp *commonhttp.Http, body []byte) error
func (api *Api) Request(method, uri string, buf []byte, resCb ApiResCallBack) error {
var hp = commonhttp.Http{SeqNo: api.opt.seqNo}
var url = ""
var count = 0
var err error
for count < api.opt.tryCount {
count++
_, err = api.GetAccessToken()
if err != nil {
return err
}
url = uri
if api.opt.buildUrlFn != nil {
url = api.opt.buildUrlFn(uri, api.opt.token, api.opt.data)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
url = req.BuildUrl(uri, api.opt.token, api.opt.data)
}
}
if url == "" {
return fmt.Errorf("url is empty")
}
if api.IsDebug() {
url += "&debug=1"
}
body, err := hp.DoWithHead(method, url, buf, func(h *http.Header) {
if api.opt.setHeadFn != nil {
api.opt.setHeadFn(h, api.opt.token)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
req.SetHead(h, api.opt.token)
}
}
})
if err != nil {
return err
}
err = resCb(&hp, body)
var res Result
if errors.As(err, &res) {
if res.IsTryCount() && count < api.opt.tryCount {
continue
}
}
return err
}
return Error(-1, "exception")
}
func (api *Api) Upload(uri string, field string, file Form, resCb ApiResCallBack) error {
var bodyBuf = bytes.Buffer{}
var w = multipart.NewWriter(&bodyBuf)
var err = file.CreateForm(w, field)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
var bodyLen = bodyBuf.Len()
if bodyLen == 0 {
return fmt.Errorf("content length is emtpy")
}
if _, err = api.GetAccessToken(); err != nil {
return err
}
var hp = commonhttp.Http{SeqNo: api.opt.seqNo}
if hp.LogEnabled() {
logger.N("Api", "Upload seqNo= '%s'", api.opt.seqNo)
}
var url = uri
if api.opt.buildUrlFn != nil {
url = api.opt.buildUrlFn(uri, api.opt.token, api.opt.data)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
url = req.BuildUrl(uri, api.opt.token, api.opt.data)
}
}
if url == "" {
return fmt.Errorf("url is empty")
}
if api.IsDebug() {
url += "&debug=1"
}
body, er := hp.Do("POST", url, &bodyBuf, func(h *http.Header) {
if api.opt.setHeadFn != nil {
api.opt.setHeadFn(h, api.opt.token)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
req.SetHead(h, api.opt.token)
}
}
h.Set("Content-Type", w.FormDataContentType())
h.Set("Content-Length", fmt.Sprintf("%d", bodyLen))
})
if er != nil {
return err
}
return resCb(&hp, body)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/h79/gothird.git
git@gitee.com:h79/gothird.git
h79
gothird
gothird
v1.8.127

搜索帮助

344bd9b3 5694891 D2dac590 5694891