package api import ( "bytes" "context" "encoding/json" "math/rand" "net/http" "github.com/go-redis/redis/v8" ) type HttpClient struct { ua string redis *redis.Client } func NewHttpClient(ua string, redis *redis.Client) *HttpClient { return &HttpClient{ua, redis} } func (c *HttpClient) SendGet(api, url string, data, out any) error { res, err := c.sendRequest(api, url, http.MethodGet, data) if err != nil { return err } decoder := json.NewDecoder(res.Body) err = decoder.Decode(&out) if err != nil { return err } return nil } func (c *HttpClient) SendPost(api, url string, data, out any) (any, error) { res, err := c.sendRequest(api, url, http.MethodPost, data) if err != nil { return nil, err } decoder := json.NewDecoder(res.Body) err = decoder.Decode(out) if err != nil { return nil, err } return out, nil } func (c *HttpClient) sendRequest(api, url, method string, data any) (*http.Response, error) { apiUrl := c.getApiUrl(api) + url client := &http.Client{} json, err := json.Marshal(&data) if err != nil { return nil, err } req, err := http.NewRequest(method, apiUrl, bytes.NewBuffer(json)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("User-Agent", c.ua) res, err := client.Do(req) if err != nil { return nil, err } // defer res.Body.Close() return res, nil } func (c *HttpClient) getApiUrl(api string) string { ctx, key, apiAddr := context.Background(), "internal__"+api+"__ips", api // FIXME: key name ^^ cmd := c.redis.LLen(ctx, key) if cmd.Err() == nil { len := int(cmd.Val()) if len == 0 { apiAddr = c.redis.LIndex(ctx, key, 0).Val() } else { apiAddr = c.redis.LIndex(ctx, key, int64(rand.Intn(len-0)+0)).Val() } } if apiAddr == "" { apiAddr = api // default api run on 80 int port } return "https://" + apiAddr }