Files
at-container-registry/pkg/appview/holdclient/tier_query.go

64 lines
1.7 KiB
Go

package holdclient
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"atcr.io/pkg/atproto"
)
// HoldTierInfo describes a single tier from a hold's listTiers response.
type HoldTierInfo struct {
Name string `json:"name"`
QuotaBytes int64 `json:"quotaBytes"`
QuotaFormatted string `json:"quotaFormatted"`
ScanOnPush bool `json:"scanOnPush"`
}
// HoldTiersResponse is the response from a hold's io.atcr.hold.listTiers endpoint.
type HoldTiersResponse struct {
Tiers []HoldTierInfo `json:"tiers"`
}
// ListTiers queries a hold's public listTiers endpoint to get tier definitions.
// No authentication is required.
func ListTiers(ctx context.Context, holdDID string) (*HoldTiersResponse, error) {
holdURL, err := atproto.ResolveHoldURL(ctx, holdDID)
if err != nil {
return nil, fmt.Errorf("could not resolve hold DID to URL: %w", err)
}
url := strings.TrimSuffix(holdURL, "/") + atproto.HoldListTiers
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to query listTiers on %s: %w", holdDID, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("listTiers on %s returned %d: %s", holdDID, resp.StatusCode, string(body))
}
var result HoldTiersResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode listTiers response from %s: %w", holdDID, err)
}
return &result, nil
}