cloudflare

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package cloudflare is a small client for the parts of the Cloudflare v4 REST API that `flue relay setup` needs: verifying a user's API token, listing the accounts it can reach, and deploying the relay Worker — script, Durable Object, static assets and all — into the account they choose.

It is deliberately not a general Cloudflare SDK. Every endpoint here exists because one step of the setup flow needs it, and the request shapes are pinned by fixtures in client_test.go rather than inferred, because the parts of this API that matter most (the asset upload session, the multipart script metadata) are the parts the published documentation describes least precisely. Where the docs and Cloudflare's own clients disagreed, the fixtures follow the clients — see the notes on hashOf and on migrations.

The API token is a field on Client and is never logged: it goes into an Authorization header and nowhere else. Client.String redacts it so that a stray %v cannot undo that.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	Code    int
	Message string
}

APIError is a failure Cloudflare reported inside its own envelope, as opposed to a transport failure. It carries the first error's code and message, which are what the setup flow shows the user.

func (*APIError) Error

func (e *APIError) Error() string

type Account

type Account struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

Account is one Cloudflare account the token can act on.

type Asset

type Asset struct {
	Path string // e.g. "/index.html", "/assets/index-abc.js"
	Body []byte
}

Asset is one file of the relay's web bundle.

type Client

type Client struct {
	HTTP  *http.Client
	Token string
	Base  string // default https://api.cloudflare.com/client/v4
}

Client talks to the Cloudflare v4 REST API with a user-supplied token. The zero value is usable and targets the real API.

func (*Client) Accounts

func (c *Client) Accounts(ctx context.Context) ([]Account, error)

Accounts lists the accounts the token can act on, so setup can ask which one the relay should live in. It follows pagination to the last page.

func (*Client) Deploy

func (c *Client) Deploy(ctx context.Context, in DeployInput) error

Deploy uploads the assets, then PUTs the script with its metadata.

The order is forced: the script's metadata has to name a completion token that only the finished asset upload can produce.

func (*Client) EnableSubdomain

func (c *Client) EnableSubdomain(ctx context.Context, accountID, script string) (string, error)

EnableSubdomain makes the script reachable on workers.dev and returns the full host, e.g. "flue-relay.<sub>.workers.dev".

func (Client) GoString

func (c Client) GoString() string

GoString redacts the token under %#v.

func (*Client) SetSecret

func (c *Client) SetSecret(ctx context.Context, accountID, script, name, value string) error

SetSecret sets a secret on the script. Cloudflare stores it as a `secret_text` binding, so the Worker reads it off env like any other binding but the value is never readable back.

func (Client) String

func (c Client) String() string

String redacts the token. Client is carried through the setup flow next to things that do get logged, and the token must never be one of them.

The receiver is a value, not a pointer, because a pointer receiver would leave `%v` on a Client value printing the token verbatim — and a Client is small enough to be passed around by value. GoString covers `%#v`, which ignores Stringer entirely and would otherwise dump every field.

func (*Client) VerifyToken

func (c *Client) VerifyToken(ctx context.Context) error

VerifyToken checks the token is real, active, and usable, so that setup can fail on a bad token before it has created anything.

type DeployInput

type DeployInput struct {
	AccountID         string
	ScriptName        string // "flue-relay"
	Module            []byte // the built worker, ESM
	CompatibilityDate string // "2026-08-01"

	// Migrations is the Durable Object migration history, oldest first — the
	// whole of it, on every deploy, exactly as relay/wrangler.jsonc holds it.
	// Deploy sends only the part this account has not applied yet; see
	// deployedMigrationTag and pendingMigrations.
	//
	// It is the history and not "what is new this time" because only the
	// history can answer that question: which steps are outstanding depends on
	// the tag the deployed script carries, which is a fact about the account
	// rather than about this binary.
	Migrations []Migration

	// OnNote, when set, hears the conditions this client can detect and cannot
	// fix — one line, already a whole sentence, for the caller to show a human.
	// It is not progress: nothing routine reaches it, and a deploy that has
	// nothing to say says nothing.
	//
	// It exists for one case today and that case used to be silent: a script
	// carrying a migration tag this binary has never heard of. Deploy then
	// sends no migration at all, deliberately, and if the upload is refused the
	// user is left with a 10061 about a Durable Object class and no hint that
	// the relay was deployed by a newer flue than the one they are running.
	OnNote func(line string)

	DOBindings           map[string]string // name -> class: {"HUB": "DaemonHub"}
	Assets               []Asset
	AssetsRunWorkerFirst []string // ["/daemon", "/client", "/api/*"]

	// PlainTextVars become bindings of type "plain_text": ordinary,
	// non-secret env vars the Worker can read. The relay's version stamp
	// travels this way. Values here are visible to anyone who can read the
	// script in the dashboard — nothing secret may ever ride one.
	PlainTextVars map[string]string

	// RateLimits become bindings of type "ratelimit" — Cloudflare's Workers
	// rate-limiting binding, the same object wrangler's `ratelimits` config
	// key produces. The wire shape is
	// {"type":"ratelimit","name":…,"namespace_id":…,"simple":{"limit":…,"period":…}},
	// pinned by testdata/deploy_metadata.json.
	RateLimits []RateLimit

	// AssetHeaders is a `_headers` document — response headers for the static
	// assets, in the file format Cloudflare's asset router parses. Empty sends
	// no header config at all. See assetsConfig.Headers for why this travels in
	// the script metadata rather than as a file among the assets.
	//
	// It applies to responses the asset router produces, including the ones a
	// Worker asks for through its assets binding, and not to responses the
	// Worker constructs itself.
	AssetHeaders string

	// AssetsBinding is the name the Worker reads its static assets off env
	// under — "ASSETS" for the relay, matching `assets.binding` in
	// relay/wrangler.jsonc. It is emitted as a binding of type "assets".
	//
	// This is separate from attaching the assets at all, and the distinction is
	// easy to get wrong: the completion token in metadata.assets.jwt makes
	// Cloudflare's *router* serve the files, and that alone is enough for a
	// Worker that only ever needs static paths served for it. It does not
	// create env.<name>. A Worker that calls env.ASSETS.fetch(...) itself — as
	// the relay does, to fall through to the SPA on unmatched /api/* — needs
	// this binding too, or that call is on undefined at runtime.
	//
	// Empty means no binding, which is correct for a router-only deploy.
	AssetsBinding string

	// Observability turns on Workers Logs for the script, matching
	// `"observability": {"enabled": true}` in relay/wrangler.jsonc. Without it
	// a relay deployed by `flue relay setup` would have no logs to debug from
	// where a wrangler-deployed one would.
	Observability bool
}

DeployInput is everything one deploy of the relay Worker needs.

type Migration added in v0.2.0

type Migration struct {
	Tag              string
	NewSQLiteClasses []string
}

Migration is one entry of the Durable Object migration history: a tag, and the classes that entry introduces. It is the Go spelling of one element of `migrations` in relay/wrangler.jsonc, and the two must stay identical — tags included — or a Worker deployed by wrangler and one deployed by `flue relay setup` carry different histories for the same classes and neither tool can deploy over the other's.

The classes must be *SQLite* classes: the free plan offers no other storage backend for Durable Objects, so a key-value migration would shut free accounts out of the relay entirely.

type RateLimit added in v0.2.0

type RateLimit struct {
	Name        string
	NamespaceID string
	Limit       int
	Period      int
}

RateLimit is one Workers rate-limiting binding: name is what the Worker reads it off env as, namespace_id keys the limiter's state (unique per limiter within the account), and limit/period are the rule — at most limit requests per period seconds per key per Cloudflare location. Cloudflare accepts only 10 or 60 for period.

Jump to

Keyboard shortcuts

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