Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

Generic Cloudflare Edge API Cache Gateway

A reusable Cloudflare Worker that authenticates API requests, proxies them to an existing origin, and edge-caches only explicitly approved responses. The origin remains authoritative and unknown routes bypass cache.

The reusable implementation contains no project-specific routes, claims, or origin header names. Project behavior lives in two configuration files:

  • src/gateway.config.ts: auth adapter, JWT claims, identity-to-origin header mappings, cache routes, mutation routes, TTLs, tags, purge path, and public observability header names.
  • wrangler.jsonc: Worker name, origin URL, JWT issuer/audience, environments, and Cloudflare runtime settings.

Secrets remain Cloudflare secrets rather than source configuration.

Default safety state

The gateway starts with zero cacheable routes. Every request goes to the configured origin until a read route is explicitly added to cacheRules. The .invalid hostnames prevent accidental deployment with placeholder values.

Workers Caching is disabled on the public gateway entrypoint and enabled only on CachedApi. Authentication therefore runs before every cache lookup. Tenant or user identity is passed to the cached entrypoint through trusted ctx.props, making it part of the cache key.

If edge authentication fails or a required scope identity is missing, caching is bypassed and the original backend handles the request normally.

Reuse for another project

1. Edit src/gateway.config.ts

The bundled default uses HS256 bearer JWTs:

auth: {
  authenticate: createHs256JwtAuthenticator({
    clockSkewSeconds: 30,
    tenantClaim: "tenant_id",
    userClaim: "sub",
  }),
},

Replace authenticate with another function for RS256/JWKS, Cloudflare Access, opaque sessions, or a different identity model. It returns a verified { tenantId?, userId? } or null. Returning null safely disables caching for that request.

Map verified identity fields into headers required by the origin:

originIdentityHeaders: [
  { header: "x-institution-id", source: "tenantId" },
],

The gateway always removes client-provided versions of configured identity headers. For a verified request, it replaces them from verified identity. For an unverifiable request, caching is bypassed and the backend receives the bearer token without any untrusted identity header, so the backend remains authoritative for rejection or fallback behavior.

Add only reviewed cache routes:

cacheRules: [
  {
    methods: ["GET"],
    pattern: /^\/api\/v1\/courses\/?$/,
    scope: "tenant",
    ttlSeconds: 60,
    tags: () => ["courses"],
  },
],

Scopes are:

  • global: identical for every authenticated caller.
  • tenant: identical for every caller in one tenant.
  • user: isolated by both tenant and user.

Only opt in responses that are identical within their declared scope. A tenant-scoped route, for example, must not vary by user role, permissions, cookies, or another header that is absent from the cache identity. Requests carrying Cookie bypass edge caching by default.

Add mutation rules whose logical tags match their dependent reads. Successful mutations are returned even if invalidation fails.

2. Edit wrangler.jsonc

Set a unique Worker name and real values for:

  • ORIGIN_BASE_URL
  • AUTH_ISSUER
  • AUTH_AUDIENCE

Keep the origin on a hostname that does not route back through this Worker.

3. Set secrets

npx wrangler secret put AUTH_JWT_SECRET --env production
npx wrangler secret put PURGE_TOKEN --env production

Never store production secrets in gateway.config.ts or wrangler.jsonc.

Origin request behavior

Uncached requests retain their original bearer token. For a cacheable request, the public gateway removes Authorization before entering Workers Caching; on a miss, CachedApi restores it only for the origin fetch. Authorization tokens never form the reusable cache identity.

Requests carrying Cookie bypass edge caching. Unsuccessful responses, partial responses, responses with Set-Cookie, and responses without a safe scope are forced to no-store.

External invalidation

The protected purge endpoint supports mutations performed by jobs, imports, scripts, or internal services:

curl -X POST https://api.example.com/__internal/cache/purge \
  -H 'Authorization: Bearer <PURGE_TOKEN>' \
  -H 'Content-Type: application/json' \
  --data '{"scope":"tenant","tenantId":"tenant-123","tags":["courses","course:42"]}'

Tenant tags are automatically namespaced. Use Cloudflare Access or mTLS in addition to the purge token when available.

Local validation

Prefer running installation and deployment from a development workstation or CI runner instead of a production VPS:

cp .dev.vars.example .dev.vars
npm install
npm run types
npm run check
npm run deploy:dry-run

Only deploy after the auth mapping and every enabled route have been reviewed:

npm run deploy

Cross-version caching is intentionally disabled, so each deployment starts with an isolated cache.

Observability

The default response headers are:

  • X-Edge-Cache: EDGE_HIT | EDGE_MISS | BYPASS | ORIGIN
  • X-Edge-Request-Id

Both names are configurable. Cloudflare invocation logs provide request metadata, status, and total duration automatically. The gateway emits only structured cache outcome events (EDGE_HIT, EDGE_MISS, BYPASS, or ORIGIN), invalidations, and errors. Workers traces sample outbound origin timing without manual request timers. No tokens, query strings, bodies, or response data are logged.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages