diff --git a/api/basket.go b/api/basket.go new file mode 100644 index 0000000..c8a422d --- /dev/null +++ b/api/basket.go @@ -0,0 +1,36 @@ +package api + +import ( + "fmt" + + def "git.pbiernat.dev/egommerce/api-entities/http" + "github.com/go-redis/redis/v8" +) + +func NewBasketAPI(redis *redis.Client) *BasketAPI { + return &BasketAPI{NewHttpClient(redis)} +} + +type BasketAPI struct { + httpClient *HttpClient +} + +func (a *BasketAPI) GetBasket(basketID string) (*def.GetBasketResponse, error) { + req := &def.GetBasketRequest{BasketID: basketID} + res := new(def.GetBasketResponse) + if err := a.httpClient.SendGet("basket", "/api/v1/basket", req, res); err != nil { + return nil, err + } + + return res, nil +} + +func (a *BasketAPI) GetBasketItems(basketID string) ([]*def.GetBasketItemsResponse, error) { + url := fmt.Sprintf("/api/v1/basket/%s/items", basketID) + var res []*def.GetBasketItemsResponse + if err := a.httpClient.SendGet("basket", url, nil, &res); err != nil { + return nil, err + } + + return res, nil +} diff --git a/api/http.go b/api/http.go new file mode 100644 index 0000000..c5ab4c1 --- /dev/null +++ b/api/http.go @@ -0,0 +1,98 @@ +package api + +import ( + "bytes" + "context" + "encoding/json" + "math/rand" + "net/http" + + "github.com/go-redis/redis/v8" +) + +const ( + HEADER_USER_AGENT = "order-httpclient" +) + +type HttpClient struct { + redis *redis.Client +} + +func NewHttpClient(redis *redis.Client) *HttpClient { + return &HttpClient{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", HEADER_USER_AGENT) + 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 "http://" + apiAddr +} diff --git a/api/pricing.go b/api/pricing.go new file mode 100644 index 0000000..0d577bc --- /dev/null +++ b/api/pricing.go @@ -0,0 +1,26 @@ +package api + +import ( + "fmt" + + def "git.pbiernat.dev/egommerce/api-entities/http" + "github.com/go-redis/redis/v8" +) + +func NewPricingAPI(redis *redis.Client) *PricingAPI { + return &PricingAPI{NewHttpClient(redis)} +} + +type PricingAPI struct { + httpClient *HttpClient +} + +func (a *PricingAPI) GetProductPrice(productID int) (*def.ProductPriceResponse, error) { + url := fmt.Sprintf("/api/v1/product/%d", productID) + res := new(def.ProductPriceResponse) + if err := a.httpClient.SendGet("pricing", url, nil, res); err != nil { + return nil, err + } + + return res, nil +}