185 lines
4.9 KiB
Go
185 lines
4.9 KiB
Go
package packages
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/paramah/ai_devs4/s01e03/internal/domain"
|
|
)
|
|
|
|
// APIClient implements domain.PackageClient
|
|
type APIClient struct {
|
|
baseURL string
|
|
apiKey string
|
|
client *http.Client
|
|
verbose bool
|
|
}
|
|
|
|
// NewAPIClient creates a new package API client
|
|
func NewAPIClient(baseURL, apiKey string, verbose bool) *APIClient {
|
|
return &APIClient{
|
|
baseURL: baseURL,
|
|
apiKey: apiKey,
|
|
client: &http.Client{},
|
|
verbose: verbose,
|
|
}
|
|
}
|
|
|
|
type checkRequest struct {
|
|
APIKey string `json:"apikey"`
|
|
Action string `json:"action"`
|
|
PackageID string `json:"packageid"`
|
|
}
|
|
|
|
type checkResponse struct {
|
|
Status string `json:"status"`
|
|
Location string `json:"location,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
type redirectRequest struct {
|
|
APIKey string `json:"apikey"`
|
|
Action string `json:"action"`
|
|
PackageID string `json:"packageid"`
|
|
Destination string `json:"destination"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
type redirectResponse struct {
|
|
Status string `json:"status"`
|
|
Message string `json:"message,omitempty"`
|
|
Confirmation string `json:"confirmation,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// Check checks the status of a package
|
|
func (c *APIClient) Check(ctx context.Context, packageID string) (*domain.PackageStatus, error) {
|
|
reqBody := checkRequest{
|
|
APIKey: c.apiKey,
|
|
Action: "check",
|
|
PackageID: packageID,
|
|
}
|
|
|
|
jsonData, err := json.Marshal(reqBody)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("marshaling request: %w", err)
|
|
}
|
|
|
|
if c.verbose {
|
|
var prettyJSON bytes.Buffer
|
|
if err := json.Indent(&prettyJSON, jsonData, "", " "); err == nil {
|
|
log.Printf("\n========== PACKAGE API CHECK REQUEST ==========\nURL: %s\nBody:\n%s\n===============================================\n", c.baseURL, prettyJSON.String())
|
|
}
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("sending request: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading response: %w", err)
|
|
}
|
|
|
|
if c.verbose {
|
|
var prettyJSON bytes.Buffer
|
|
if err := json.Indent(&prettyJSON, body, "", " "); err == nil {
|
|
log.Printf("\n========== PACKAGE API CHECK RESPONSE ==========\nStatus: %d\nBody:\n%s\n================================================\n", resp.StatusCode, prettyJSON.String())
|
|
}
|
|
}
|
|
|
|
var apiResp checkResponse
|
|
if err := json.Unmarshal(body, &apiResp); err != nil {
|
|
return nil, fmt.Errorf("unmarshaling response: %w", err)
|
|
}
|
|
|
|
if apiResp.Error != "" {
|
|
return nil, fmt.Errorf("API error: %s", apiResp.Error)
|
|
}
|
|
|
|
return &domain.PackageStatus{
|
|
PackageID: packageID,
|
|
Status: apiResp.Status,
|
|
Location: apiResp.Location,
|
|
}, nil
|
|
}
|
|
|
|
// Redirect redirects a package to a new destination and returns the confirmation message
|
|
func (c *APIClient) Redirect(ctx context.Context, packageID, destination, code string) (string, error) {
|
|
reqBody := redirectRequest{
|
|
APIKey: c.apiKey,
|
|
Action: "redirect",
|
|
PackageID: packageID,
|
|
Destination: destination,
|
|
Code: code,
|
|
}
|
|
|
|
jsonData, err := json.Marshal(reqBody)
|
|
if err != nil {
|
|
return "", fmt.Errorf("marshaling request: %w", err)
|
|
}
|
|
|
|
if c.verbose {
|
|
var prettyJSON bytes.Buffer
|
|
if err := json.Indent(&prettyJSON, jsonData, "", " "); err == nil {
|
|
log.Printf("\n========== PACKAGE API REDIRECT REQUEST ==========\nURL: %s\nBody:\n%s\n==================================================\n", c.baseURL, prettyJSON.String())
|
|
}
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, bytes.NewBuffer(jsonData))
|
|
if err != nil {
|
|
return "", fmt.Errorf("creating request: %w", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.client.Do(req)
|
|
if err != nil {
|
|
return "", fmt.Errorf("sending request: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", fmt.Errorf("reading response: %w", err)
|
|
}
|
|
|
|
if c.verbose {
|
|
var prettyJSON bytes.Buffer
|
|
if err := json.Indent(&prettyJSON, body, "", " "); err == nil {
|
|
log.Printf("\n========== PACKAGE API REDIRECT RESPONSE ==========\nStatus: %d\nBody:\n%s\n===================================================\n", resp.StatusCode, prettyJSON.String())
|
|
}
|
|
}
|
|
|
|
var apiResp redirectResponse
|
|
if err := json.Unmarshal(body, &apiResp); err != nil {
|
|
return "", fmt.Errorf("unmarshaling response: %w", err)
|
|
}
|
|
|
|
if apiResp.Error != "" {
|
|
return "", fmt.Errorf("API error: %s", apiResp.Error)
|
|
}
|
|
|
|
// Return the confirmation code
|
|
if apiResp.Confirmation != "" {
|
|
return apiResp.Confirmation, nil
|
|
}
|
|
|
|
// Fallback to message if confirmation is not present
|
|
return apiResp.Message, nil
|
|
}
|