git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/bunny/client.go (about) 1 package bunny 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "io" 8 "net/http" 9 10 "git.sr.ht/~pingoo/stdx/httpx" 11 ) 12 13 type Client struct { 14 httpClient *http.Client 15 acountApiKey string 16 apiBaseURL string 17 streamApiBaseUrl string 18 streamApiKey string 19 } 20 21 func NewClient(acountApiKey, streamApiKey string, httpClient *http.Client) *Client { 22 if httpClient == nil { 23 httpClient = httpx.DefaultClient() 24 } 25 26 return &Client{ 27 httpClient: httpClient, 28 acountApiKey: acountApiKey, 29 streamApiKey: streamApiKey, 30 apiBaseURL: "https://api.bunny.net", 31 streamApiBaseUrl: "https://video.bunnycdn.com", 32 } 33 } 34 35 type requestParams struct { 36 Method string 37 URL string 38 Payload interface{} 39 useStreamApiKey bool 40 } 41 42 type uploadParams struct { 43 Method string 44 URL string 45 Data io.Reader 46 useStreamApiKey bool 47 } 48 49 type APIError struct { 50 Message string 51 } 52 53 func (res APIError) Error() string { 54 return res.Message 55 } 56 57 func (client *Client) request(ctx context.Context, params requestParams, dst interface{}) error { 58 req, err := http.NewRequestWithContext(ctx, params.Method, params.URL, nil) 59 if err != nil { 60 return err 61 } 62 63 if params.Payload != nil { 64 payloadData, err := json.Marshal(params.Payload) 65 if err != nil { 66 return err 67 } 68 req.Body = io.NopCloser(bytes.NewBuffer(payloadData)) 69 } 70 71 apiKey := client.acountApiKey 72 if params.useStreamApiKey { 73 apiKey = client.streamApiKey 74 } 75 76 req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson) 77 req.Header.Add(httpx.HeaderContentType, httpx.MediaTypeJson) 78 req.Header.Add("AccessKey", apiKey) 79 80 res, err := client.httpClient.Do(req) 81 if err != nil { 82 return err 83 } 84 defer res.Body.Close() 85 86 body, err := io.ReadAll(res.Body) 87 if err != nil { 88 return err 89 } 90 91 if res.StatusCode >= 400 { 92 var apiErr APIError 93 94 err = json.Unmarshal(body, &apiErr) 95 if err != nil { 96 return err 97 } 98 99 return apiErr 100 } else if dst != nil { 101 err = json.Unmarshal(body, dst) 102 } 103 104 return err 105 } 106 107 func (client *Client) upload(ctx context.Context, params uploadParams, dst interface{}) error { 108 req, err := http.NewRequestWithContext(ctx, params.Method, params.URL, params.Data) 109 if err != nil { 110 return err 111 } 112 113 apiKey := client.acountApiKey 114 if params.useStreamApiKey { 115 apiKey = client.streamApiKey 116 } 117 118 req.Header.Add(httpx.HeaderAccept, httpx.MediaTypeJson) 119 req.Header.Add(httpx.HeaderContentType, "application/octet-stream") 120 req.Header.Add("AccessKey", apiKey) 121 122 res, err := client.httpClient.Do(req) 123 if err != nil { 124 return err 125 } 126 defer res.Body.Close() 127 128 body, err := io.ReadAll(res.Body) 129 if err != nil { 130 return err 131 } 132 133 if res.StatusCode >= 400 { 134 var apiErr APIError 135 136 err = json.Unmarshal(body, &apiErr) 137 if err != nil { 138 return err 139 } 140 141 return apiErr 142 } else if dst != nil { 143 err = json.Unmarshal(body, dst) 144 } 145 146 return err 147 }