github.com/LagrangeDev/LagrangeGo@v0.0.0-20240512064304-ad4a85e10cb4/client/sign/http.go (about) 1 package sign 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net/http" 9 "net/url" 10 "strconv" 11 "time" 12 13 "github.com/LagrangeDev/LagrangeGo/client/http2" 14 ) 15 16 var ( 17 signMap = map[string]struct{}{} // 只在启动时初始化, 无并发问题 18 ) 19 20 func init() { 21 signPkgList := []string{ 22 "trpc.o3.ecdh_access.EcdhAccess.SsoEstablishShareKey", 23 "trpc.o3.ecdh_access.EcdhAccess.SsoSecureAccess", 24 "trpc.o3.report.Report.SsoReport", 25 "MessageSvc.PbSendMsg", 26 // "wtlogin.trans_emp", 27 "wtlogin.login", 28 // "trpc.login.ecdh.EcdhService.SsoKeyExchange", 29 "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLogin", 30 "trpc.login.ecdh.EcdhService.SsoNTLoginEasyLogin", 31 "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginNewDevice", 32 "trpc.login.ecdh.EcdhService.SsoNTLoginEasyLoginUnusualDevice", 33 "trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginUnusualDevice", 34 "OidbSvcTrpcTcp.0x11ec_1", 35 "OidbSvcTrpcTcp.0x758_1", 36 "OidbSvcTrpcTcp.0x7c2_5", 37 "OidbSvcTrpcTcp.0x10db_1", 38 "OidbSvcTrpcTcp.0x8a1_7", 39 "OidbSvcTrpcTcp.0x89a_0", 40 "OidbSvcTrpcTcp.0x89a_15", 41 "OidbSvcTrpcTcp.0x88d_0", 42 "OidbSvcTrpcTcp.0x88d_14", 43 "OidbSvcTrpcTcp.0x112a_1", 44 "OidbSvcTrpcTcp.0x587_74", 45 "OidbSvcTrpcTcp.0x1100_1", 46 "OidbSvcTrpcTcp.0x1102_1", 47 "OidbSvcTrpcTcp.0x1103_1", 48 "OidbSvcTrpcTcp.0x1107_1", 49 "OidbSvcTrpcTcp.0x1105_1", 50 "OidbSvcTrpcTcp.0xf88_1", 51 "OidbSvcTrpcTcp.0xf89_1", 52 "OidbSvcTrpcTcp.0xf57_1", 53 "OidbSvcTrpcTcp.0xf57_106", 54 "OidbSvcTrpcTcp.0xf57_9", 55 "OidbSvcTrpcTcp.0xf55_1", 56 "OidbSvcTrpcTcp.0xf67_1", 57 "OidbSvcTrpcTcp.0xf67_5", 58 } 59 60 for _, cmd := range signPkgList { 61 signMap[cmd] = struct{}{} 62 } 63 } 64 65 func containSignPKG(cmd string) bool { 66 _, ok := signMap[cmd] 67 return ok 68 } 69 70 func NewProviderURL(rawUrl string, log func(msg string)) func(string, uint32, []byte) map[string]string { 71 if rawUrl == "" { 72 return nil 73 } 74 return func(cmd string, seq uint32, buf []byte) map[string]string { 75 if !containSignPKG(cmd) { 76 return nil 77 } 78 startTime := time.Now().UnixMilli() 79 resp := signResponse{} 80 err := httpGet(rawUrl, map[string]string{ 81 "cmd": cmd, 82 "seq": strconv.Itoa(int(seq)), 83 "src": fmt.Sprintf("%x", buf), 84 }, 8*time.Second, &resp) 85 if err != nil { 86 log(err.Error()) 87 return nil 88 } 89 90 log(fmt.Sprintf("signed for [%s:%d](%dms)", 91 cmd, seq, time.Now().UnixMilli()-startTime)) 92 93 return map[string]string{ 94 "sign": resp.Value.Sign, 95 "extra": resp.Value.Extra, 96 "token": resp.Value.Token, 97 } 98 } 99 } 100 101 func httpGet(rawUrl string, queryParams map[string]string, timeout time.Duration, target interface{}) error { 102 u, err := url.Parse(rawUrl) 103 if err != nil { 104 return fmt.Errorf("failed to parse URL: %w", err) 105 } 106 107 q := u.Query() 108 for k, v := range queryParams { 109 q.Set(k, v) 110 } 111 u.RawQuery = q.Encode() 112 113 ctx, cancel := context.WithTimeout(context.Background(), timeout) 114 defer cancel() 115 116 req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) 117 if err != nil { 118 return fmt.Errorf("failed to create GET request: %w", err) 119 } 120 121 resp, err := http2.TRSClient.Do(req) 122 if err != nil { 123 if errors.Is(ctx.Err(), context.DeadlineExceeded) { 124 return fmt.Errorf("request timed out") 125 } 126 resp, err = http2.DefaultClient.Do(req) 127 if err != nil { 128 if errors.Is(ctx.Err(), context.DeadlineExceeded) { 129 return fmt.Errorf("request timed out") 130 } 131 return fmt.Errorf("failed to perform GET request: %w", err) 132 } 133 } 134 defer resp.Body.Close() 135 136 if resp.StatusCode != http.StatusOK { 137 return fmt.Errorf("unexpected status code: %d", resp.StatusCode) 138 } 139 140 if err := json.NewDecoder(resp.Body).Decode(target); err != nil { 141 return fmt.Errorf("failed to unmarshal JSON response: %w", err) 142 } 143 144 return nil 145 } 146 147 type signResponse struct { 148 Value struct { 149 Sign string `json:"sign"` 150 Extra string `json:"extra"` 151 Token string `json:"token"` 152 } `json:"value"` 153 }