|
@@ -0,0 +1,224 @@
|
|
|
+package v1
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "crypto/md5"
|
|
|
+ "encoding/hex"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "io/ioutil"
|
|
|
+ "metawant.greentech.com.cn/gaoyagang/gt-common/datacenter_client"
|
|
|
+ "metawant.greentech.com.cn/gaoyagang/gt-common/httplib"
|
|
|
+ "net/http"
|
|
|
+ "net/url"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+type (
|
|
|
+ DcApi struct {
|
|
|
+ options ClientOptions
|
|
|
+ }
|
|
|
+
|
|
|
+ // ClientOptions 客户端配置选项
|
|
|
+ ClientOptions struct {
|
|
|
+ httplib.HTTPSettings
|
|
|
+ ServerIp string
|
|
|
+ AppName string
|
|
|
+ AppSecret string
|
|
|
+
|
|
|
+ DoBefore []func(r *httplib.HTTPRequest) error
|
|
|
+ DoAfter []func(r *httplib.HTTPRequest) error
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+func NewDcApi(options ClientOptions) *DcApi {
|
|
|
+ dcapi := &DcApi{}
|
|
|
+
|
|
|
+ if len(options.DoBefore) == 0 {
|
|
|
+ options.DoBefore = make([]func(r *httplib.HTTPRequest) error, 0)
|
|
|
+ }
|
|
|
+ options.DoBefore = append(options.DoBefore, dcapi.signMiddleware)
|
|
|
+
|
|
|
+ dcapi.options = options
|
|
|
+
|
|
|
+ return dcapi
|
|
|
+}
|
|
|
+
|
|
|
+// SetHttpSettings 设置客户端选择
|
|
|
+// ShowDebug bool
|
|
|
+// UserAgent string
|
|
|
+// TLSClientConfig *tls.Config
|
|
|
+// Proxy func(*http.Request) (*url.URL, error)
|
|
|
+// Transport http.RoundTripper
|
|
|
+// CheckRedirect func(req *http.Request, via []*http.Request) error
|
|
|
+// EnableCookie bool
|
|
|
+// Gzip bool
|
|
|
+// DumpBody bool
|
|
|
+// Retries int // if set to -1 means will retry forever
|
|
|
+// ConnectTimeout time.Duration
|
|
|
+// KeepAlive time.Duration
|
|
|
+// Timeout time.Duration
|
|
|
+func (d *DcApi) SetHttpSettings(settings httplib.HTTPSettings) {
|
|
|
+ d.options.HTTPSettings = settings
|
|
|
+}
|
|
|
+
|
|
|
+func (d *DcApi) serviceUrl(serviceName string) string {
|
|
|
+ return fmt.Sprintf("%s%s%s%s", "http://", d.options.ServerIp, "/api/dtgateway/v1", serviceName)
|
|
|
+}
|
|
|
+
|
|
|
+// 实际执行请求
|
|
|
+func (d *DcApi) call(r *httplib.HTTPRequest, resp any) error {
|
|
|
+ for _, bf := range d.options.DoBefore {
|
|
|
+ if err := bf(r); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ response, err := r.Response()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ if response.StatusCode != http.StatusOK {
|
|
|
+ msg, _ := r.String()
|
|
|
+ return errors.New(fmt.Sprintf("response status code: %d, body: %s", response.StatusCode, msg))
|
|
|
+ }
|
|
|
+
|
|
|
+ if xerr := r.ToJSON(resp); err != nil {
|
|
|
+ return errors.New(fmt.Sprintf("response to json error %s", xerr.Error()))
|
|
|
+ }
|
|
|
+
|
|
|
+ // 这里应该增加一个记录日志的after
|
|
|
+ for _, af := range d.options.DoAfter {
|
|
|
+ if err := af(r); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// 数据签名middleware
|
|
|
+func (d *DcApi) signMiddleware(r *httplib.HTTPRequest) error {
|
|
|
+ // 验证公共参数
|
|
|
+ if d.options.AppName == "" {
|
|
|
+ return errors.New(fmt.Sprintf("error: %d app name empty", datacenter_client.DC_PARAMS_APP_NAME_MISSION))
|
|
|
+ }
|
|
|
+
|
|
|
+ if d.options.AppSecret == "" {
|
|
|
+ return errors.New(fmt.Sprintf("error: %d app secret empty", datacenter_client.DC_PARAMS_APP_SECRET_MISSION))
|
|
|
+ }
|
|
|
+
|
|
|
+ queryParams := r.GetQueryParam()
|
|
|
+ if pids, ok := queryParams["project_id"]; !ok || len(pids) == 0 {
|
|
|
+ return errors.New(fmt.Sprintf("error: %d project id empty", datacenter_client.DC_PARAMS_PROJECT_ID_MISSION))
|
|
|
+ } else {
|
|
|
+ r.Param("project_id", pids[0])
|
|
|
+ }
|
|
|
+
|
|
|
+ r.Param("ts", fmt.Sprintf("%d", time.Now().Unix()))
|
|
|
+ sign, err := CalcSign(r, d.options.AppSecret)
|
|
|
+ if err != nil {
|
|
|
+ return errors.New(fmt.Sprintf("error: %d check data sign error", datacenter_client.DC_DATA_SIGN_ERROR))
|
|
|
+ }
|
|
|
+
|
|
|
+ r.Param("sign", sign)
|
|
|
+
|
|
|
+ // 设置headers信息
|
|
|
+ r.Header("APP-NAME", d.options.AppName)
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func cutS2(s2 string) string {
|
|
|
+ if s2 == "" {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+ s2l := len(s2)
|
|
|
+ //if s2l <= S2_MIN_LENGTH {
|
|
|
+ // return s2
|
|
|
+ //}
|
|
|
+ return fmt.Sprintf("%s%s", s2[:datacenter_client.S2_HEAD_LENGTH], s2[s2l-datacenter_client.S2_TAIL_LENGTH:])
|
|
|
+}
|
|
|
+
|
|
|
+func sortS2(s2 string) (string, error) {
|
|
|
+ if s2 == "" {
|
|
|
+ return "", nil
|
|
|
+ }
|
|
|
+ var mi map[string]interface{}
|
|
|
+ if err := json.Unmarshal([]byte(s2), &mi); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ //smi := SortMapByKey(mi)
|
|
|
+
|
|
|
+ if bs, err := json.Marshal(mi); err != nil {
|
|
|
+ return "", err
|
|
|
+ } else {
|
|
|
+ return string(bs), nil
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func CalcSign(r *httplib.HTTPRequest, secret string) (string, error) {
|
|
|
+ s2, err := parseBody(r)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("parseBody Error: ", err.Error())
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ contentLength := r.GetRequest().ContentLength
|
|
|
+ if contentLength > datacenter_client.S2_MIN_LENGTH {
|
|
|
+ r.Param("sign_flag", "1")
|
|
|
+ s2 = cutS2(s2)
|
|
|
+ } else {
|
|
|
+ s2, err = sortS2(s2)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ s3 := contentLength
|
|
|
+ s1 := parseQuery(r)
|
|
|
+
|
|
|
+ m := md5.New()
|
|
|
+ m.Write([]byte(fmt.Sprintf("%s%s%d%s", s1, s2, s3, secret)))
|
|
|
+ md5Str := hex.EncodeToString(m.Sum(nil))
|
|
|
+ //fmt.Println("s1", s1)
|
|
|
+ //fmt.Println("s2", s2)
|
|
|
+ //fmt.Println("s3", s3)
|
|
|
+ //fmt.Println("md5", md5Str)
|
|
|
+ return md5Str, nil
|
|
|
+}
|
|
|
+
|
|
|
+func parseBody(r *httplib.HTTPRequest) (s2 string, err error) {
|
|
|
+ if r.GetRequest().Method == http.MethodGet {
|
|
|
+ return "", nil
|
|
|
+ }
|
|
|
+ body := r.GetRequest().Body
|
|
|
+
|
|
|
+ cnt, err := ioutil.ReadAll(body)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ r.GetRequest().Body = ioutil.NopCloser(bytes.NewReader(cnt))
|
|
|
+
|
|
|
+ return string(cnt), nil
|
|
|
+}
|
|
|
+
|
|
|
+func parseQuery(r *httplib.HTTPRequest) string {
|
|
|
+ params := r.GetQueryParam()
|
|
|
+ delete(params, "sign")
|
|
|
+
|
|
|
+ val := url.Values{}
|
|
|
+ for k, v := range params {
|
|
|
+ for index, s := range v {
|
|
|
+ if index == 0 {
|
|
|
+ val.Set(k, s)
|
|
|
+ } else {
|
|
|
+ val.Add(k, s)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return val.Encode()
|
|
|
+}
|