1 Star 0 Fork 0

h79 / gothird

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
api.go 5.96 KB
一键复制 编辑 原始数据 按行查看 历史
huqiuyun 提交于 2023-10-23 20:27 . debug 模式
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 ResCallBack func(hp *commonhttp.Http, body []byte) error
type Api struct {
token Token
opts ApiOptions
}
type ApiOptions struct {
data.Options
token string
appId string
secret string
seqNo string
tryCount int
debug int
buildUrlFn ApiBuildUrlFunc
setHeadFn ApiSetHeadFunc
setTokenFn ApiSetTokenFunc
getTokenFn ApiGetTokenFunc
}
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 WithToken(token string) ApiOption {
return func(opts *ApiOptions) {
opts.token = token
}
}
func WithAppId(appId string) ApiOption {
return func(opts *ApiOptions) {
opts.appId = appId
}
}
func WithSecret(secret string) ApiOption {
return func(opts *ApiOptions) {
opts.secret = secret
}
}
func WithDebug() ApiOption {
return func(opts *ApiOptions) {
opts.debug = 1
}
}
func WithSeqNo(no string) ApiOption {
return func(opts *ApiOptions) {
opts.seqNo = no
}
}
func WithTryCount(count int) ApiOption {
return func(opts *ApiOptions) {
if count > 4 {
count = 4 //最多重试4次
}
opts.tryCount = count
}
}
func WithBuildUrl(fn ApiBuildUrlFunc) ApiOption {
return func(opts *ApiOptions) {
opts.buildUrlFn = fn
}
}
func WithHeadFunc(fn ApiSetHeadFunc) ApiOption {
return func(opts *ApiOptions) {
opts.setHeadFn = fn
}
}
func WithSetTokenFunc(fn ApiSetTokenFunc) ApiOption {
return func(opts *ApiOptions) {
opts.setTokenFn = fn
}
}
func WithGetTokenFunc(fn ApiGetTokenFunc) ApiOption {
return func(opts *ApiOptions) {
opts.getTokenFn = fn
}
}
func NewApi(tk Token, opts ...ApiOption) *Api {
a := &Api{token: tk, opts: ApiOptions{Options: data.Options{Data: data.D{}}, token: "", tryCount: 2, buildUrlFn: nil}}
return a.WithOptions(opts...)
}
func (api *Api) Clone() *Api {
return &Api{token: api.token, opts: api.opts}
}
type ApiOption func(opts *ApiOptions)
func (api *Api) WithOptions(opts ...ApiOption) *Api {
for i := range opts {
opts[i](&api.opts)
}
return api
}
func (api *Api) AppId() string {
if api.opts.appId != "" {
return api.opts.appId
}
if api.token != nil {
return api.token.GetAppId()
}
return ""
}
func (api *Api) IsDebug() bool {
return api.opts.debug == 1
}
func (api *Api) Secret() string {
if api.opts.secret != "" {
return api.opts.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.opts.token != "" {
return api.opts.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.opts.Data)
})
} else if api.opts.getTokenFn != nil {
tk, err = api.opts.getTokenFn(api.AppId(), api.opts.Data)
} else {
panic("internal error")
}
api.setToken(tk)
return api.opts.token, err
}
func (api *Api) setToken(tk string) {
api.opts.token = tk
if api.opts.setTokenFn != nil {
api.opts.setTokenFn(api.AppId(), api.opts.token)
}
}
func (api *Api) Request(method, uri string, buf []byte, resCb ResCallBack) error {
var hp = commonhttp.Http{SeqNo: api.opts.seqNo}
if hp.LogEnabled() {
logger.NDebug("Request seqNo= '%s', Body= '%s'", api.opts.seqNo, logger.Byte2(logger.NDebugLevel, buf))
}
var url = ""
var count = 0
for count < api.opts.tryCount {
count++
if _, err := api.GetAccessToken(); err != nil {
return err
}
url = uri
if api.opts.buildUrlFn != nil {
url = api.opts.buildUrlFn(uri, api.opts.token, api.opts.Data)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
url = req.BuildUrl(uri, api.opts.token, api.opts.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.opts.setHeadFn != nil {
api.opts.setHeadFn(h, api.opts.token)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
req.SetHead(h, api.opts.token)
}
}
})
if err != nil {
return err
}
er := resCb(&hp, body)
var res Result
if errors.As(er, &res) {
if res.IsTryCount() && count < api.opts.tryCount {
continue
}
}
return er
}
return Error(-1, "exception")
}
func (api *Api) Upload(uri string, field string, file Form, resCb ResCallBack) 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.opts.seqNo}
if hp.LogEnabled() {
logger.NDebug("Upload seqNo= '%s'", api.opts.seqNo)
}
var url = uri
if api.opts.buildUrlFn != nil {
url = api.opts.buildUrlFn(uri, api.opts.token, api.opts.Data)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
url = req.BuildUrl(uri, api.opts.token, api.opts.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.opts.setHeadFn != nil {
api.opts.setHeadFn(h, api.opts.token)
} else if api.token != nil {
if req := api.token.GetRequest(); req != nil {
req.SetHead(h, api.opts.token)
}
}
h.Set("Content-Type", w.FormDataContentType())
h.Set("Content-Length", fmt.Sprintf("%d", bodyLen))
})
if er != nil {
return err
}
return resCb(&hp, body)
}
1
https://gitee.com/h79/gothird.git
git@gitee.com:h79/gothird.git
h79
gothird
gothird
v1.8.103

搜索帮助