package extapi import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" ) // Client mendefinisikan kontrak fleksibel untuk mengirim HTTP request ke pihak ketiga/API internal. type Client interface { PostJSON(ctx context.Context, url string, token string, payload interface{}) ([]byte, int, error) GetJSON(ctx context.Context, url string, token string) ([]byte, int, error) } type clientImpl struct { httpClient *http.Client } // NewClient membuat instance baru dari Client dengan batas timeout tertentu. func NewClient(timeout time.Duration) Client { return &clientImpl{ httpClient: &http.Client{Timeout: timeout}, } } func (c *clientImpl) PostJSON(ctx context.Context, url string, token string, payload interface{}) ([]byte, int, error) { jsonData, err := json.Marshal(payload) if err != nil { return nil, 0, fmt.Errorf("gagal marshal payload: %w", err) } req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData)) if err != nil { return nil, 0, fmt.Errorf("gagal membuat request: %w", err) } req.Header.Set("Content-Type", "application/json") if token != "" { req.Header.Set("Authorization", "Bearer "+token) } res, err := c.httpClient.Do(req) if err != nil { return nil, 0, fmt.Errorf("request gagal dieksekusi: %w", err) } defer res.Body.Close() respBody, err := io.ReadAll(res.Body) if err != nil { return nil, res.StatusCode, fmt.Errorf("gagal membaca body response: %w", err) } return respBody, res.StatusCode, nil } func (c *clientImpl) GetJSON(ctx context.Context, url string, token string) ([]byte, int, error) { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return nil, 0, fmt.Errorf("gagal membuat request: %w", err) } req.Header.Set("Accept", "application/json") if token != "" { req.Header.Set("Authorization", "Bearer "+token) } res, err := c.httpClient.Do(req) if err != nil { return nil, 0, fmt.Errorf("request gagal dieksekusi: %w", err) } defer res.Body.Close() respBody, err := io.ReadAll(res.Body) if err != nil { return nil, res.StatusCode, fmt.Errorf("gagal membaca body response: %w", err) } return respBody, res.StatusCode, nil }