client

package
v0.2.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package client provides a typed Go client for the Beamdrop S3-compatible API.

The client handles HMAC-SHA256 request signing, bucket and object operations, and both client-side and server-side presigned URL generation.

Example usage:

ctx := context.Background()
client, err := client.New(client.Config{
	BaseURL:     "http://localhost:7777",
	AccessKeyID: "BDK_abc123",
	SecretKey:   "sk_secret",
})
if err != nil {
	log.Fatal(err)
}

// Create or reuse a bucket
_, err = client.CreateBucketIfNotExists(ctx, "my-bucket")
if err != nil {
	log.Fatal(err)
}

// Upload an object
_, err = client.PutObject(ctx, "my-bucket", "path/to/file.txt", []byte("hello world"))
if err != nil {
	log.Fatal(err)
}

// Download an object
obj, err := client.GetObject(ctx, "my-bucket", "path/to/file.txt")
if err != nil {
	log.Fatal(err)
}
fmt.Println(string(obj.Body))

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidBaseURL indicates that the provided BaseURL is empty, malformed, or missing scheme/host.
	ErrInvalidBaseURL = errors.New("invalid base URL")

	// ErrMissingCredentials indicates that AccessKeyID and SecretKey are required but not both provided.
	// If one is provided, both must be provided.
	ErrMissingCredentials = errors.New("missing beamdrop credentials")

	// ErrInvalidPath indicates that an internal request path is invalid or empty.
	ErrInvalidPath = errors.New("invalid path")
)

Functions

This section is empty.

Types

type APIError

type APIError struct {
	// StatusCode is the HTTP status code of the response (e.g., 404, 409, 429).
	StatusCode int `json:"-"`

	// Code is the machine-readable error code (e.g., "BUCKET_NOT_FOUND", "RATE_LIMIT_EXCEEDED").
	Code string `json:"code,omitempty"`

	// Category is the error category (e.g., "NOT_FOUND", "CONFLICT", "RATE_LIMIT").
	Category string `json:"category,omitempty"`

	// Message is the human-readable error message.
	Message string `json:"message,omitempty"`

	// Details is optional structured data providing additional context about the error.
	Details map[string]any `json:"details,omitempty"`

	// Retryable indicates whether the operation can be safely retried.
	// True for rate limiting and service unavailable errors.
	Retryable bool `json:"-"`

	// RetryAfter is the recommended number of seconds to wait before retrying.
	// Set from the Retry-After response header if present.
	RetryAfter int `json:"-"`

	// Body is the raw response body for debugging and inspection.
	Body []byte `json:"-"`
}

APIError represents a structured error response from the Beamdrop API. It includes the HTTP status code, error code, category, human-readable message, and retry information.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface, returning a formatted error message.

type BucketCreated

type BucketCreated struct {
	// Bucket is the name of the bucket.
	Bucket string `json:"bucket"`
	// Created is the RFC3339 timestamp when the bucket was created (only if newly created).
	Created string `json:"created,omitempty"`
	// Exists indicates whether the bucket already existed (used in CreateBucketIfNotExists response).
	Exists bool `json:"exists,omitempty"`
	// Location is the API path to the bucket resource.
	Location string `json:"location"`
}

BucketCreated is the response from CreateBucket and CreateBucketIfNotExists.

type BucketInfo

type BucketInfo struct {
	Name      string    `json:"name"`
	CreatedAt time.Time `json:"createdAt"`
}

BucketInfo represents metadata about a single bucket.

type BucketList

type BucketList struct {
	// Buckets is a slice of all accessible buckets.
	Buckets []BucketInfo `json:"buckets"`
	// Count is the total number of buckets.
	Count int `json:"count"`
}

BucketList is the response from ListBuckets.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a typed Beamdrop S3-compatible API client. It handles HMAC-SHA256 request signing, response decoding, and error handling. All methods accept a context for cancellation and timeouts.

func New

func New(config Config) (*Client, error)

New creates and returns a new Beamdrop API client configured with the provided Config. It validates the base URL and initializes default values for HTTPClient, Now, and UserAgent if not provided.

Returns an error if the base URL is invalid or empty.

func (*Client) BucketExists

func (c *Client) BucketExists(ctx context.Context, name string) (bool, error)

BucketExists checks whether a bucket exists using a HEAD request. Returns true if the bucket exists, false if it returns a 404, or an error for other failures.

func (*Client) CreateBucket

func (c *Client) CreateBucket(ctx context.Context, name string) (*BucketCreated, error)

CreateBucket creates a new bucket with the given name. Returns an error if the bucket already exists (status 409) or if the name is invalid. See CreateBucketIfNotExists for an idempotent variant.

func (*Client) CreateBucketIfNotExists

func (c *Client) CreateBucketIfNotExists(ctx context.Context, name string) (*BucketCreated, error)

CreateBucketIfNotExists creates a bucket if it does not already exist, returning an idempotent operation. Returns 201 Created if the bucket was newly created, or 200 OK with exists=true if it already existed. Recommended for initialization and bootstrap use cases.

func (*Client) CreatePresignedURL

func (c *Client) CreatePresignedURL(ctx context.Context, request CreatePresignedURLRequest) (*PresignedURL, error)

CreatePresignedURL creates a server-side presigned URL with optional download limits and revocation support. The URL is stored in Beamdrop's presigned URL registry and can be revoked at any time. ExpiresIn is specified in seconds; if nil, the URL never expires (depends on server policy). MaxDownloads limits the number of times the presigned URL can be used; if nil, unlimited. Returns a PresignedURL containing the token and the full URL.

func (*Client) DeleteBucket

func (c *Client) DeleteBucket(ctx context.Context, name string) error

DeleteBucket deletes an empty bucket. Returns an error if the bucket is not found (404) or if it contains objects (409). Delete all objects in the bucket before calling this method.

func (*Client) DeleteObject

func (c *Client) DeleteObject(ctx context.Context, bucket, key string) error

DeleteObject deletes an object from a bucket. Returns an error if the object is not found (404) or if the deletion fails.

func (*Client) DeletePresignedURL

func (c *Client) DeletePresignedURL(ctx context.Context, token string) error

DeletePresignedURL revokes a server-side presigned URL by its token. The URL becomes invalid immediately and cannot be used for access.

func (*Client) GetObject

func (c *Client) GetObject(ctx context.Context, bucket, key string) (*ObjectBody, error)

GetObject downloads an object from a bucket with the given key. The entire object is read into memory and returned in ObjectBody.Body. For very large objects, consider using a presigned URL and a standard HTTP client instead.

func (*Client) GetPresignedURL

func (c *Client) GetPresignedURL(ctx context.Context, token string) (*PresignedURL, error)

GetPresignedURL retrieves a single server-side presigned URL by its token. Returns an error if the token is not found or has expired.

func (*Client) HeadObject

func (c *Client) HeadObject(ctx context.Context, bucket, key string) (*ObjectMetadata, error)

HeadObject retrieves metadata about an object without downloading the body. Returns content type, length, ETag, and last modified timestamp.

func (*Client) ListBuckets

func (c *Client) ListBuckets(ctx context.Context) (*BucketList, error)

ListBuckets returns a list of all buckets accessible with the configured credentials. Returns BucketList containing bucket names and creation timestamps.

func (*Client) ListObjects

func (c *Client) ListObjects(ctx context.Context, bucket string, options ListObjectsOptions) (*ObjectList, error)

ListObjects lists objects in a bucket with optional prefix, delimiter, and max key limit. Supports S3-style hierarchical listing with delimiters and common prefixes. MaxKeys defaults to 1000 if not specified.

func (*Client) ListPresignedURLs

func (c *Client) ListPresignedURLs(ctx context.Context) (*PresignedURLList, error)

ListPresignedURLs lists all server-side presigned URLs created with this API key. Returns a PresignedURLList containing all tokens, buckets, keys, and metadata.

func (*Client) ObjectExists

func (c *Client) ObjectExists(ctx context.Context, bucket, key string) (bool, error)

ObjectExists checks whether an object exists using a HEAD request. Returns true if the object exists, false if it returns a 404, or an error for other failures.

func (*Client) PresignObjectURL

func (c *Client) PresignObjectURL(method, bucket, key string, expiresAt time.Time) (string, error)

PresignObjectURL generates a client-side presigned URL for direct access to an object. The URL is self-contained, signed using your secret key, and does not require server involvement. Method should be "GET" or "PUT". The expiresAt timestamp is in UTC. Note: key rotation will invalidate existing presigned URLs generated this way. For more control over expiration and revocation, use CreatePresignedURL (server-side).

func (*Client) PutObject

func (c *Client) PutObject(ctx context.Context, bucket, key string, body []byte) (*ObjectCreated, error)

PutObject uploads an object (file) to a bucket with the given key (path). The body is provided as a byte slice. For streaming uploads, use PutObjectReader. Returns object metadata including ETag and size on success.

func (*Client) PutObjectReader

func (c *Client) PutObjectReader(ctx context.Context, bucket, key string, body io.Reader) (*ObjectCreated, error)

PutObjectReader uploads an object from an io.Reader, supporting streaming for large files. The reader is consumed completely during upload. Provide a buffered or seekable reader for retries. Returns object metadata including ETag and size on success.

type CommonPrefix

type CommonPrefix struct {
	// Prefix is the shared prefix string for a group of objects.
	Prefix string `json:"prefix"`
}

CommonPrefix represents a common prefix (directory-like grouping) in a ListObjects result.

type Config

type Config struct {
	// BaseURL is the base URL of the Beamdrop server (required).
	// Example: "http://localhost:7777" or "https://files.example.com".
	BaseURL string

	// AccessKeyID is the public API access key identifier (optional for anonymous access).
	// Format: "BDK_xxxx" where xxxx is the key ID.
	AccessKeyID string

	// SecretKey is the private API secret key (required if AccessKeyID is set).
	// Format: "sk_xxxx" where xxxx is the secret key material.
	SecretKey string

	// HTTPClient is the underlying HTTP client used for requests (optional).
	// If nil, a default client with 2-minute timeout is used.
	HTTPClient *http.Client

	// Now is a function that returns the current time in UTC (optional).
	// Used for generating request timestamps. If nil, time.Now().UTC() is used.
	// Primarily for testing and time mocking.
	Now func() time.Time

	// UserAgent is the User-Agent header sent with requests (optional).
	// If empty, defaults to "beamdrop-go-client/0.1".
	UserAgent string
}

Config holds the configuration for creating a new Beamdrop API client.

type CreatePresignedURLRequest

type CreatePresignedURLRequest struct {
	// Bucket is the target bucket name (required).
	Bucket string `json:"bucket"`
	// Key is the target object key/path (required).
	Key string `json:"key"`
	// Method is the HTTP method for the presigned URL ("GET" or "PUT"; defaults to "GET").
	Method string `json:"method,omitempty"`
	// ExpiresIn is the expiration time in seconds from now (optional).
	// If nil, the presigned URL never expires (subject to server policy).
	ExpiresIn *int64 `json:"expiresIn,omitempty"`
	// MaxDownloads limits the number of times the presigned URL can be used (optional).
	// If nil, the URL is unlimited in use.
	MaxDownloads *int `json:"maxDownloads,omitempty"`
}

CreatePresignedURLRequest configures a CreatePresignedURL request.

type ListObjectsOptions

type ListObjectsOptions struct {
	// Prefix filters the listing to objects whose keys start with this string.
	Prefix string
	// Delimiter groups objects by this separator (commonly "/" for hierarchical listing).
	Delimiter string
	// MaxKeys limits the number of objects returned (default 1000 if not specified).
	MaxKeys int
}

ListObjectsOptions configures a ListObjects request.

type ObjectBody

type ObjectBody struct {
	// ObjectMetadata contains headers like content type, length, and ETag.
	ObjectMetadata
	// Body is the complete object content as a byte slice.
	Body []byte
}

ObjectBody is the response from GetObject, containing both metadata and the object body.

type ObjectCreated

type ObjectCreated struct {
	// Bucket is the bucket where the object was stored.
	Bucket string `json:"bucket"`
	// Key is the object's path/key.
	Key string `json:"key"`
	// ETag is the MD5 hash of the uploaded content.
	ETag string `json:"etag"`
	// Size is the total size of the uploaded object in bytes.
	Size int64 `json:"size"`
	// URL is the API path to the object resource.
	URL string `json:"url"`
}

ObjectCreated is the response from PutObject and PutObjectReader.

type ObjectInfo

type ObjectInfo struct {
	// Key is the object's path/key within the bucket.
	Key string `json:"key"`
	// Size is the object's size in bytes.
	Size int64 `json:"size"`
	// LastModified is the RFC3339 timestamp of the last modification.
	LastModified time.Time `json:"lastModified"`
	// ETag is the MD5 hash of the object content, useful for detecting changes.
	ETag string `json:"etag"`
	// ContentType is the MIME type detected from the object key extension.
	ContentType string `json:"contentType,omitempty"`
}

ObjectInfo represents metadata about a single object in a bucket.

type ObjectList

type ObjectList struct {
	// Bucket is the bucket being listed.
	Bucket string `json:"bucket"`
	// Prefix is the prefix filter used in the request.
	Prefix string `json:"prefix"`
	// Delimiter is the delimiter used for grouping (typically "/").
	Delimiter string `json:"delimiter,omitempty"`
	// MaxKeys is the maximum number of keys requested.
	MaxKeys int `json:"maxKeys"`
	// IsTruncated indicates whether there are more results to fetch.
	IsTruncated bool `json:"isTruncated"`
	// Contents is the list of objects matching the prefix and delimiter.
	Contents []ObjectInfo `json:"contents"`
	// CommonPrefixes is a list of shared prefixes (for hierarchical listing with a delimiter).
	CommonPrefixes []CommonPrefix `json:"commonPrefixes,omitempty"`
}

ObjectList is the response from ListObjects. It includes both object listings and common prefixes (for hierarchical S3-style listing).

type ObjectMetadata

type ObjectMetadata struct {
	// ContentType is the MIME type of the object.
	ContentType string
	// ContentLength is the size of the object in bytes.
	ContentLength int64
	// ETag is the MD5 hash of the object content.
	ETag string
	// LastModified is the RFC1123 formatted timestamp of the last modification.
	LastModified string
}

ObjectMetadata contains HTTP headers from a HEAD or GET request for an object.

type PresignedURL

type PresignedURL struct {
	// ID is the unique database identifier (internal).
	ID uint `json:"id,omitempty"`
	// Token is the unique token for this presigned URL (used in /dl/{token}).
	Token string `json:"token"`
	// URL is the full presigned URL (including scheme, host, path, and parameters).
	URL string `json:"url,omitempty"`
	// Bucket is the target bucket name.
	Bucket string `json:"bucket"`
	// Key is the target object key/path.
	Key string `json:"key"`
	// Method is the HTTP method allowed for this presigned URL.
	Method string `json:"method"`
	// ExpiresAt is the expiration timestamp in RFC3339 format (nil if never expires).
	ExpiresAt *time.Time `json:"expiresAt,omitempty"`
	// MaxDownloads is the maximum number of times this URL can be used (nil if unlimited).
	MaxDownloads *int `json:"maxDownloads,omitempty"`
	// DownloadCount is the current number of times the presigned URL has been used.
	DownloadCount int `json:"downloadCount,omitempty"`
	// CreatedBy is the access key ID that created this presigned URL.
	CreatedBy string `json:"createdBy,omitempty"`
	// CreatedAt is the RFC3339 timestamp when this presigned URL was created.
	CreatedAt time.Time `json:"createdAt"`
	// Message is an optional message from the server (e.g., error details).
	Message string `json:"message,omitempty"`
}

PresignedURL represents a server-side presigned URL record in Beamdrop's registry.

type PresignedURLList

type PresignedURLList struct {
	// URLs is the list of all presigned URL records.
	URLs []PresignedURL `json:"urls"`
	// Count is the total number of presigned URLs.
	Count int `json:"count"`
}

PresignedURLList is the response from ListPresignedURLs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL