-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.go
More file actions
81 lines (71 loc) · 2.03 KB
/
utils.go
File metadata and controls
81 lines (71 loc) · 2.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package gosparkclient
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"
"time"
)
// assembleAuthURL generates the authenticated URL for API requests
func (c *SparkClient) assembleAuthURL(httpMethod string, hostURL string) string {
ul, err := url.Parse(hostURL)
if err != nil {
panic(fmt.Sprintf("invalid URL: %v", err))
}
date := time.Now().UTC().Format(time.RFC1123)
signString := []string{
"host: " + ul.Host,
"date: " + date,
httpMethod + " " + ul.Path + " HTTP/1.1",
}
signature := hmacSha256ToBase64(strings.Join(signString, "\n"), c.config.ApiSecret)
authorization := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(
"hmac username=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",
c.config.ApiKey,
"hmac-sha256",
"host date request-line",
signature,
)))
v := url.Values{}
v.Add("host", ul.Host)
v.Add("date", date)
v.Add("authorization", authorization)
return hostURL + "?" + v.Encode()
}
// hmacSha256ToBase64 generates an HMAC-SHA256 signature and returns it as base64
func hmacSha256ToBase64(data, key string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(data))
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
// defaultTransport creates a default HTTP transport with the given timeout
func defaultTransport(timeout time.Duration) *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: timeout,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: 100,
}
}
// readBody reads and returns the response body as a string
func readBody(resp *http.Response) string {
if resp == nil {
return ""
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Sprintf("error reading response body: %v", err)
}
return fmt.Sprintf("code=%d,body=%s", resp.StatusCode, string(b))
}