http

package
v0.14.1 Latest Latest
Warning

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

Go to latest
Published: Mar 16, 2026 License: MIT Imports: 14 Imported by: 0

README

pkg/http

HTTP client with zstd compression, TLS enforcement, retry logic, and typed errors.

Files

File Role
client.go Client struct, DoJSON method, compression, retries, error handling

Key API

client := http.NewClient(cfg, timeout)
err := client.Post("/api/v1/sync/chunk", reqBody, &respBody)
  • NewClient(cfg, timeout) — Creates client with zstd encoder, TLS config, and timeout.
  • DoJSON(method, path, reqBody, respBody) — Core method: marshals JSON, optionally compresses, sends request, handles retries/errors, unmarshals response.
  • Get / Post / Patch — Convenience wrappers around DoJSON.
  • SetUserAgent(ua) — Package-level function, must be called once at startup (from main.go).

Sentinel Errors

Error HTTP Status Meaning
ErrUnauthorized 401, 403 Invalid or expired API key
ErrRateLimited 429 Rate limited after max retries
ErrSessionNotFound 404 Session doesn't exist on backend
ErrConflict 409 Duplicate resource

Callers use errors.Is(err, http.ErrUnauthorized) to handle specific cases.

Design Decisions

Zstd over gzip. Better compression ratio for JSON payloads, which matters for large transcript chunks. The 1KB compression threshold (compressionThreshold) avoids compressing tiny payloads where overhead exceeds savings.

Retry only on 429. Rate limiting is transient and retryable. Other errors (400, 500) are not retried — they indicate bugs or server issues that won't resolve by waiting. Retries use exponential backoff (1s initial, 2x multiplier, 60s max) and respect Retry-After headers.

Localhost TLS exemption. Non-localhost URLs enforce TLS 1.2+. Localhost is exempt for local development. This is checked by hostname, not scheme.

Never log payloads. DoJSON logs payload byte counts but never the content. Payloads contain transcript data which may include sensitive information even after redaction.

How to Extend

Adding a new error type: Define a sentinel error (var ErrFoo = errors.New("...")), add a case in DoJSON's status code switch, and document it above.

Changing retry behavior: Modify maxRetries, initialBackoff, maxBackoff, or backoffMultiplier constants. Consider that retry changes affect all API calls.

Invariants

  • SetUserAgent() must be called once at startup before any HTTP requests.
  • TLS 1.2+ is enforced for all non-localhost connections — do not weaken this.
  • Payloads must never be logged (privacy).
  • Retry logic must only apply to 429 responses.

Testing

go test ./pkg/http/...

Tests use httptest.NewServer to verify compression thresholds, error handling, and retry behavior.

Dependencies

Uses: github.com/klauspost/compress/zstd, pkg/config (UploadConfig for backend URL/API key), pkg/logger

Used by: pkg/sync/ (via Client), cmd/ (login, status validation)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrConflict = errors.New("conflict")

ErrConflict is returned when the server returns 409. This typically means the resource already exists (e.g., duplicate link).

View Source
var ErrRateLimited = errors.New("rate limited")

ErrRateLimited is returned when retries are exhausted on 429 responses.

View Source
var ErrSessionNotFound = errors.New("session not found")

ErrSessionNotFound is returned when the server returns 404. This typically means the session was deleted from the backend.

View Source
var ErrUnauthorized = errors.New("unauthorized")

ErrUnauthorized is returned when the server returns 401 or 403. This typically means the API key is invalid or expired.

Functions

func BuildUserAgent

func BuildUserAgent(version string) string

BuildUserAgent constructs a User-Agent string in the format: confab/version (os; arch)

func SetUserAgent

func SetUserAgent(ua string)

SetUserAgent sets the User-Agent header for all HTTP requests. Should be called once at startup before any requests are made.

Types

type Client

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

Client is a configured HTTP client for making authenticated requests to the backend

func NewClient

func NewClient(cfg *config.UploadConfig, timeout time.Duration) (*Client, error)

NewClient creates a new authenticated HTTP client

func (*Client) DoJSON

func (c *Client) DoJSON(method, path string, reqBody, respBody interface{}) error

DoJSON performs an HTTP request with JSON body and parses JSON response Automatically sets Content-Type, Authorization, and handles error responses. Payloads larger than 1KB are compressed with zstd. Retries with exponential backoff on 429 (rate limited) responses.

func (*Client) Get

func (c *Client) Get(path string, respBody interface{}) error

Get performs a GET request with JSON response parsing

func (*Client) Patch

func (c *Client) Patch(path string, reqBody, respBody interface{}) error

Patch performs a PATCH request with JSON body and response

func (*Client) Post

func (c *Client) Post(path string, reqBody, respBody interface{}) error

Post performs a POST request with JSON body and response

Jump to

Keyboard shortcuts

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