package main import ( "bytes" "crypto/hmac" "crypto/md5" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "io/ioutil" "math/rand" "net/http" "sort" "strings" "time" "github.com/pkg/errors" ) type BaseResp struct { Code int64 `json:"code"` Message string `json:"message"` RequestId string `json:"request_id"` Data WebsocketInfoResp `json:"data"` } type WebsocketInfoResp struct { Ip []string `json:"ip"` AuthBody string `json:"auth_body"` Host []string `json:"host"` TcpPort []int64 `json:"tcp_port"` WsPort []int64 `json:"ws_port"` WssPort []int64 `json:"wss_port"` } func hmacSHA256(key string, data string) string { mac := hmac.New(sha256.New, []byte(key)) mac.Write([]byte(data)) return hex.EncodeToString(mac.Sum(nil)) } func toSortedString(headerMap map[string]string) string { mapKeys := make([]string, 0, len(headerMap)) for k := range headerMap { mapKeys = append(mapKeys, k) } sort.Strings(mapKeys) headerStr := "" for _, mapKey := range mapKeys { headerStr += fmt.Sprintf("%v:%v\n", mapKey, headerMap[mapKey]) } return strings.TrimRight(headerStr, "\n") } func Sign(params map[string]interface{}, key, secret string) map[string]string { paramStr, _ := json.Marshal(params) md5Str := fmt.Sprintf("%x", md5.Sum(paramStr)) now := time.Now().Unix() headerMap := map[string]string{ "x-bili-accesskeyid": key, "x-bili-content-md5": md5Str, "x-bili-signature-method": "HMAC-SHA256", "x-bili-signature-version": "1.0", "x-bili-signature-nonce": fmt.Sprintf("%v", rand.Int63n(100000)+now), "x-bili-timestamp": fmt.Sprintf("%v", now), } headerStr := toSortedString(headerMap) headerMap["Authorization"] = hmacSHA256(secret, headerStr) headerMap["Content-Type"] = "application/json" headerMap["Accept"] = "application/json" return headerMap } func SendPost(url, key, secret string, params map[string]interface{}) (*http.Response, error) { paramsBytes, _ := json.Marshal(params) header := Sign(params, key, secret) req, err := http.NewRequest("POST", url, bytes.NewBuffer(paramsBytes)) if err != nil { return nil, err } for k, v := range header { req.Header.Set(k, v) } client := &http.Client{} return client.Do(req) } func GetWebsocketInfo(akId, akSecret string) (host string, port int64, authBody string, err error) { resp, err := SendPost(fmt.Sprintf("%s/v1/common/websocketInfo", TestHttpHost), akId, akSecret, map[string]interface{}{}) body, _ := ioutil.ReadAll(resp.Body) infoData := &BaseResp{} if err = json.Unmarshal(body, infoData); err != nil { err = errors.Wrapf(err, "[websocketInfo | GetWebsocketInfo] json.Unmarshal err resp:%+v", resp) return } // fmt.Printf("%#v\n", infoData.Data) // 这里简单写下,实际可以根据需求取 if len(infoData.Data.WsPort) != 0 && len(infoData.Data.Host) != 0 { host, port, authBody = infoData.Data.Host[0], infoData.Data.WsPort[0], infoData.Data.AuthBody } return }