Files
telecom-platform/apps/cli/internal/api/client.go
T
nutcas3 bd3226edf0 feat: Refactor CLI API client by splitting billing, carrier, and charging modules into separate files
- Extract Invoice, Payment, Subscriber types and GetInvoices, GetPayments, GenerateInvoice methods to billing.go
- Extract CarrierInfo, ConnectivityStatus, ProfileInfo types and carrier connector methods to carrier.go
- Extract CreditCheckRequest/Response, CreditBalanceResponse types and charging engine methods to charging.go
- Add PacketStats, CreditInfo types and GetPacketStats, GetCreditInfo
2026-04-25 05:33:41 +03:00

137 lines
3.1 KiB
Go

package api
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/nutcas3/telecom-platform/apps/cli/internal/types"
)
// Client represents the API client for the telecom platform
type Client struct {
baseURL string
apiKey string
httpClient *http.Client
}
// NewClient creates a new API client from CLI config
func NewClient(cfg *types.CLIConfig) *Client {
if cfg == nil {
cfg = &types.CLIConfig{APIEndpoint: "http://localhost:8000"}
}
return &Client{
baseURL: cfg.APIEndpoint,
apiKey: cfg.APIToken,
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
}
}
// BaseURL returns the configured API endpoint (useful for UI display).
func (c *Client) BaseURL() string {
return c.baseURL
}
// doGetJSON performs a GET request and decodes JSON into out
func (c *Client) doGetJSON(path string, out any) error {
req, err := http.NewRequest("GET", c.baseURL+path, nil)
if err != nil {
return err
}
if c.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+c.apiKey)
}
req.Header.Set("Content-Type", "application/json")
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("API %s %d: %s", path, resp.StatusCode, string(body))
}
return json.NewDecoder(resp.Body).Decode(out)
}
// doPostJSON performs a POST request with JSON body and decodes response
func (c *Client) doPostJSON(path string, body any, out any) error {
var buf *bytes.Buffer
if body != nil {
b, err := json.Marshal(body)
if err != nil {
return err
}
buf = bytes.NewBuffer(b)
} else {
buf = bytes.NewBuffer(nil)
}
req, err := http.NewRequest("POST", c.baseURL+path, buf)
if err != nil {
return err
}
if c.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+c.apiKey)
}
req.Header.Set("Content-Type", "application/json")
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
rb, _ := io.ReadAll(resp.Body)
return fmt.Errorf("API %s %d: %s", path, resp.StatusCode, string(rb))
}
if out == nil {
return nil
}
return json.NewDecoder(resp.Body).Decode(out)
}
// doDelete performs a DELETE request
func (c *Client) doDelete(path string) error {
req, err := http.NewRequest("DELETE", c.baseURL+path, nil)
if err != nil {
return err
}
if c.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+c.apiKey)
}
resp, err := c.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("API %s %d: %s", path, resp.StatusCode, string(body))
}
return nil
}
// IsConnected checks if the API server is reachable
func (c *Client) IsConnected() bool {
url := fmt.Sprintf("%s/health", c.baseURL)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return false
}
req.Header.Set("Authorization", "Bearer "+c.apiKey)
resp, err := c.httpClient.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == http.StatusOK
}