Skip to content

ChristianRiesen/workflowy-proxy

Repository files navigation

Workflowy Proxy

A Rust-based API proxy for Workflowy with caching, rate limiting, and authentication support.

Features

  • API Proxy: Mirrors Workflowy API endpoints at /api/v1/*
  • Caching: Smart caching with thundering herd prevention
    • Response cache for individual requests
    • Node cache populated from exports for fast lookups
    • Stale cache fallback on upstream errors
  • Tree Nesting: GET /api/v1/nodes?depth=N returns nested children up to N levels deep, sorted by priority
  • Rate Limiting: Enforced rate limit for /nodes-export endpoint
  • Authentication: Optional API key authentication via Bearer token
  • Cache Bypass: X-Cache-Bypass: true header to force fresh data
  • Cache Headers: X-Cache, X-Cache-Age, X-Cache-Source response headers

Quick Start

Docker

docker run -d \
  -p 8168:8168 \
  -e WORKFLOWY_API_KEY=your-workflowy-api-key \
  ghcr.io/christianriesen/workflowy-proxy:latest

From Source

# Clone the repository
git clone https://github.com/ChristianRiesen/workflowy-proxy.git
cd workflowy-proxy

# Build and run
cargo run --release

Configuration

All configuration is done via environment variables:

Variable Required Default Description
WORKFLOWY_API_KEY Yes - Your Workflowy API key
WORKFLOWY_API_URL No https://workflowy.com/api Workflowy API base URL
API_KEY No - Proxy authentication key (empty = no auth)
PORT No 8168 Server port
READ_CACHE_TTL_SECS No 60 Cache TTL for read operations (seconds)
NODES_EXPORT_CACHE_TTL_SECS No 60 Minimum interval between export calls
REQUEST_TIMEOUT_SECS No 180 Request timeout (seconds)
CONNECT_TIMEOUT_SECS No 5 Connection timeout (seconds)
MAX_REQUEST_SIZE No 52428800 Max request body size (50MB)
GRACEFUL_SHUTDOWN_TIMEOUT_SECS No 30 Graceful shutdown timeout
PROACTIVE_CACHE_ENABLED No false Enable proactive cache warming
PROACTIVE_CACHE_MISS_THRESHOLD No 2 Cache misses required to trigger proactive caching
PROACTIVE_CACHE_WINDOW_SECS No 60 Time window (seconds) for counting cache misses

API Endpoints

System Endpoints

Endpoint Description
GET /healthcheck Health check (always returns healthy)
GET /ready Readiness check
GET /version Version information (commit, build date)

Official WorkFlowy API Endpoints

These endpoints proxy the official WorkFlowy API.

Endpoint Description WorkFlowy Rate Limit
GET /api/v1/nodes?parent_id=X&depth=N List children of a node (with optional tree nesting) 60 per 60s bucket
GET /api/v1/nodes/:id Get a single node 60 per 60s bucket
POST /api/v1/nodes Create a new node 60 per 60s bucket
POST /api/v1/nodes/:id Update a node 60 per 60s bucket
DELETE /api/v1/nodes/:id Delete a node 60 per 60s bucket
POST /api/v1/nodes/:id/move Move a node 60 per 60s bucket
POST /api/v1/nodes/:id/complete Mark node as complete 60 per 60s bucket
POST /api/v1/nodes/:id/uncomplete Mark node as incomplete 60 per 60s bucket
GET /api/v1/nodes-export Export all nodes 1 per 60s bucket
GET /api/v1/targets List targets/shortcuts 60 per 60s bucket

WorkFlowy Rate Limiting: The WorkFlowy API uses a bucket-based rate limit. Each bucket is 60 seconds long and allows 60 requests. When the limit is exceeded, the API returns HTTP 429 with a message indicating how long until the current bucket resets. Because buckets are fixed windows, up to 120 requests can succeed within ~20 seconds if timed across a bucket boundary (60 at the end of one bucket + 60 at the start of the next). The /nodes-export endpoint has a stricter limit of 1 request per bucket.

Proxy-Only Endpoints

These endpoints are provided by the proxy and are not part of the WorkFlowy API.

Endpoint Description
GET /api/v1/nodes-export-cache Warm cache without returning data

See docs/API.md for detailed API documentation.

Authentication

If API_KEY is set, all requests to /api/v1/* endpoints require a Bearer token:

curl -H "Authorization: Bearer your-api-key" http://localhost:8168/api/v1/targets

System endpoints (/healthcheck, /ready, /version) do not require authentication.

Cache Behavior

Cache Headers

All responses include cache status headers:

  • X-Cache: HIT, MISS, or STALE
  • X-Cache-Source: response or node-cache
  • X-Cache-Age: Age of cached entry in seconds (when applicable)
  • X-Cache-Bypass-Ignored: Present when bypass was requested but ignored due to rate limiting

Cache Bypass

Add X-Cache-Bypass: true header to force a fresh fetch (bypasses cache).

Note: Cache bypass is ignored for rate-limited endpoints (/nodes-export) when within the rate limit window.

Thundering Herd Prevention

When multiple concurrent requests arrive for the same uncached data, only the first request fetches from Workflowy. Other requests wait and receive the cached result.

Proactive Cache Warming

When enabled (PROACTIVE_CACHE_ENABLED=true), the proxy detects frequent cache misses and automatically triggers a /nodes-export call to warm the cache. This is useful when many different nodes are being requested that aren't yet cached.

Recommended: Enable proactive caching for optimal performance.

  • Tracks cache misses within a sliding time window (PROACTIVE_CACHE_WINDOW_SECS)
  • Triggers warming when miss count exceeds threshold (PROACTIVE_CACHE_MISS_THRESHOLD)
  • Respects the rate limit for /nodes-export calls

Development

# Run tests
cargo test

# Run with debug logging
RUST_LOG=debug cargo run

# Format code
cargo fmt

# Run clippy
cargo clippy

License

MIT License - see LICENSE

About

No description, website, or topics provided.

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors