Web Proxy Setup
The web proxy allows the Tsumihon web app to access third-party sites that would otherwise be blocked by browser CORS policies.
Why a Proxy?
Browsers block direct requests to many doujin sites due to CORS and hotlink protections. The Cloudflare Pages Function at /api/proxy acts as a transparent server-side proxy:
- The browser talks only to your own domain.
- The proxy fetches the target site server-to-server (no CORS).
- Realistic browser headers and referer spoofing are injected.
- Cookies are tunneled to preserve login sessions.
- Responses are streamed without full buffering.
Architecture
Flutter Web → /api/proxy?url=<target>
│
▼
Cloudflare Pages Function
(functions/api/proxy.js)
│
▼
Target doujin site
Deployment
The proxy deploys automatically with Cloudflare Pages. The functions/ directory in the repository is detected and deployed as Pages Functions. No additional configuration is needed beyond setting environment variables.
Environment Variables
Set these in Cloudflare Pages → Settings → Environment Variables:
| Variable | Required | Description |
|---|---|---|
PROXY_TOKEN | Yes | Shared secret for proxy access. Must match the Flutter build token. |
PROXY_UA | No | Override the default browser User-Agent string. |
PROXY_ALLOWED_HOSTS | No | Comma-separated exact hostnames to allow (e.g., example.com,sub.example.com). |
PROXY_ALLOWED_SUFFIXES | No | Comma-separated domain suffixes (e.g., .example.org,.example.net). |
Host Allowlist
The proxy rejects any host not in the allowlist. The primary allowlist is defined in functions/allowed_hosts.json:
hosts— Exact hostnames (e.g.,nhentai.net)suffixes— Domain suffixes (e.g.,.nhentai.net)
You can also add temporary hosts via the environment variables above without redeploying.
Flutter Web Configuration
When building for web, pass these Dart defines:
flutter build web \
--dart-define=PROXY_TOKEN=your_token_here \
--dart-define=PROXY_BASE_URL=/api/proxy
The web app automatically routes all HTTP and image requests through the proxy when kIsWeb is true and PROXY_TOKEN is set. Mobile builds bypass the proxy entirely.
Cookie Tunneling
Since browsers can't set cookies for third-party domains, the proxy uses custom headers:
x-proxy-cookie— Cookies sent from the app to the proxy (forwarded to the target).x-proxy-set-cookie— Cookies returned by the target, stored locally in the app and reused on subsequent requests.
Rate Limiting
The proxy implements a token-bucket rate limiter per IP address. If you receive 429 Too Many Requests, reduce concurrency or wait before retrying.
Local Development
Two options for developing locally with the proxy:
Option 1: Use Production Proxy
Set PROXY_BASE_URL to your production domain during local development:
flutter run -d chrome \
--dart-define=PROXY_TOKEN=your_token \
--dart-define=PROXY_BASE_URL=https://tsumihon.app/api/proxy
Option 2: Run Locally with Wrangler
# Build the web app
flutter build web
# Serve with Cloudflare Pages Functions
npx wrangler pages dev build/web
Troubleshooting
403 Forbidden
- Token mismatch — ensure
PROXY_TOKENmatches between Cloudflare and your Flutter build. - Host not in allowlist — add the target host to
functions/allowed_hosts.jsonand redeploy.
429 Too Many Requests
- Rate limit triggered. Reduce concurrent requests or wait a moment.
Missing Images
- The target site may be blocking requests based on Referer. Verify the host is in the allowlist.
- Ensure
PROXY_BASE_URLis set correctly in your build.
Login Sessions Not Preserved
- Check that
x-proxy-set-cookieheaders are being returned. - Clear app cookies and log in again.
Security Notes
- The
PROXY_TOKENis visible to end users in the web app. Treat it as an access key, not a secret. - Rely on the host allowlist, rate limiting, and Cloudflare WAF for abuse prevention.
- Rotate the token if you suspect it has been leaked.