Cloudflare Workers
Inoltra le richieste a /docs tramite un Cloudflare Worker al tuo sito Jamdesk. Configurazione del Worker, pattern di route e impostazioni della cache.
Un Cloudflare Worker intercetta le richieste a /docs sul tuo dominio, le riscrive verso il tuo sottodominio Jamdesk e restituisce la risposta. Viene eseguito all'edge senza un server di origine. Genera il Worker con npx jamdesk deploy-proxy cloudflare, oppure configuralo manualmente seguendo i passaggi qui sotto.
Come funziona
Il Worker inoltra le richieste al tuo sottodominio Jamdesk. Passa il tuo dominio nell'header X-Jamdesk-Forwarded-Host. Jamdesk legge questo header per verificare il dominio e applicarne le impostazioni. È una configurazione una tantum: le modifiche successive al dominio o alla configurazione nella dashboard non richiedono un aggiornamento del Worker.
Prerequisiti
- Un account Cloudflare con il tuo dominio configurato
- Wrangler CLI v3.0+ installato
- Il tuo sottodominio Jamdesk (si trova nelle impostazioni della dashboard)
- Il tuo dominio personalizzato aggiunto al progetto nella dashboard Jamdesk (il Worker restituisce un 403 finché il dominio non è registrato e verificato)
- Un record DNS proxied (nuvola arancione) sul nome host che serve la documentazione. I Worker vengono eseguiti solo sui record proxied. Un dominio che non ospita altro richiede comunque un record: aggiungi un record
AAAAsegnaposto che punti a100::e impostalo come proxied.
Configurazione rapida con CLI
Configura il Worker con un solo comando:
npx jamdesk deploy-proxy cloudflare
Questo comando interattivo:
- Verifica che wrangler 3.0+ sia installato
- Controlla il tuo account Cloudflare e mostra i domini disponibili
- Individua il tuo sottodominio Jamdesk dal progetto collegato in
docs.json - Ti fa selezionare il dominio di destinazione tra le tue zone Cloudflare
- Genera tutti i file necessari
- Facoltativamente, esegue il deploy su Cloudflare
Se hai accesso a più account Cloudflare (comune per agenzie o team), la CLI ti chiede di sceglierne uno prima della selezione della zona. Scegli l'account che possiede il dominio su cui stai effettuando il deploy. Le route dei Worker possono essere create solo per i domini dell'account selezionato.
Configurazione non interattiva
Passa le risposte come flag per eseguire il comando senza prompt, in CI o da uno script:
jamdesk deploy-proxy cloudflare --slug myproject --domain example.com --yes
--yes genera i file del Worker e si ferma. Non esegue mai il deploy. La zona viene dedotta dal tuo dominio, non verificata rispetto al tuo account Cloudflare. Mandare in produzione questa configurazione resta un passaggio esplicito. Concludi con:
cd cloudflare-worker
npx wrangler deploy
--yes non può chiederti il sottodominio. La CLI lo legge dal progetto collegato in docs.json. Se quel collegamento manca, passa --slug (oppure esegui jamdesk deploy una volta per aggiungere il collegamento). Altrimenti il comando si ferma invece di tirare a indovinare.
Se la directory di output esiste già, --yes si ferma invece di sostituirla. Aggiungi --force per sovrascriverla, oppure --output-dir per scrivere altrove.
| Opzione | Descrizione |
|---|---|
--slug | Il tuo sottodominio Jamdesk, la X in X.jamdesk.app (salta il rilevamento automatico) |
--domain | Dominio di destinazione (ad es. yoursite.com) |
--path | Prefisso del percorso; deve corrispondere esattamente al sottopercorso nella dashboard (predefinito: /docs) |
--output-dir | Directory di output (predefinito: cloudflare-worker/) |
--skip-deploy | Salta il prompt "eseguire il deploy ora?" in un'esecuzione interattiva (--yes non esegue mai il deploy) |
--force | Sovrascrive la directory di output se esiste già |
--yes | Risponde a ogni prompt con il valore predefinito (modalità CI). Non esegue mai il deploy. Non sovrascrive mai una directory esistente, a meno che non sia combinato con --force |
Oppure segui i passaggi manuali qui sotto.
Configurazione manuale
Passaggio 1: crea un Worker
Crea una nuova directory per il tuo Worker e inizializzala:
mkdir docs-proxy && cd docs-proxy
npm init -y
Passaggio 2: aggiungi il codice del Worker
Crea index.js con il seguente codice:
/**
* Jamdesk Documentation Proxy Worker
*
* Generated by: jamdesk deploy-proxy cloudflare
* Proxies /docs/* requests AND their assets to YOUR_SLUG.jamdesk.app
*
* Assets under /_jd/* (images, fonts, branding, analytics) must also be proxied
* since they use absolute paths in the HTML.
*/
const JAMDESK_HOST = "YOUR_SLUG.jamdesk.app";
// Paths that are always proxied to Jamdesk
const PROXY_PATHS = [
"/docs", // Documentation pages
"/_jd/", // All Jamdesk assets (images, fonts, branding, analytics)
];
function shouldProxy(pathname) {
return PROXY_PATHS.some(prefix => {
// For the docs path, require exact match or prefix with slash (not /docs.json)
if (prefix === "/docs") {
return pathname === "/docs" || pathname.startsWith("/docs/");
}
return pathname.startsWith(prefix);
});
}
function proxyToJamdesk(request, url) {
// Rewrite the request to Jamdesk
const proxyUrl = new URL(request.url);
proxyUrl.hostname = JAMDESK_HOST;
// Pin the scheme: an http:// visitor proxied as http:// gets a 308 from
// Vercel's edge pointing at JAMDESK_HOST, and redirect:"manual" hands that
// redirect straight to the browser — bouncing the visitor off this domain.
proxyUrl.protocol = "https:";
// Setting .protocol leaves a non-default .port in place, so :8787 (wrangler
// dev) or Cloudflare's alternate http ports (8080, 8880, 2052…) would follow
// us to the https upstream and fail there.
proxyUrl.port = "";
// Clone headers and add proxy headers
const headers = new Headers(request.headers);
headers.set("Host", JAMDESK_HOST);
headers.set("X-Forwarded-Host", url.hostname);
headers.set("X-Forwarded-Proto", "https");
// Custom header for domain verification (Vercel strips standard forwarding headers)
headers.set("X-Jamdesk-Forwarded-Host", url.hostname);
// Don't follow redirects — let the browser handle them so the URL updates.
// Without this, redirects happen internally and the browser URL doesn't change,
// which causes the sidebar to mis-highlight the active page.
const proxyRequest = new Request(proxyUrl, {
method: request.method,
headers,
body: request.body,
redirect: "manual",
});
// Cache all content types at Cloudflare edge (CF doesn't cache HTML by default).
// Cache duration is controlled by upstream Cache-Control headers.
// Never cache redirects or errors — they must always hit origin.
return fetch(proxyRequest, {
cf: {
cacheEverything: true,
cacheTtlByStatus: { "300-399": 0, "400-499": 0, "500-599": 0 },
},
});
}
export default {
async fetch(request) {
const url = new URL(request.url);
if (shouldProxy(url.pathname)) {
return proxyToJamdesk(request, url);
}
// /_next/ is ambiguous: the customer's root site may itself be a Next.js app
// serving its own /_next/ assets. Try the origin first and fall back to
// Jamdesk when the origin doesn't have it (404) or can't answer at all
// (5xx — a docs-only domain has no real origin, so Cloudflare returns 522).
// Hashed asset filenames never collide between the two apps.
if (url.pathname.startsWith("/_next/")) {
let originResponse;
try {
originResponse = await fetch(request);
} catch (err) {
// Log rather than swallow: a genuine platform fault and a domain with
// no origin at all are indistinguishable in `wrangler tail` otherwise.
console.warn("origin fetch threw, serving from Jamdesk:", err);
return proxyToJamdesk(request, url);
}
if (originResponse.status !== 404 && originResponse.status < 500) {
return originResponse;
}
return proxyToJamdesk(request, url);
}
return fetch(request);
},
};Sostituisci YOUR_SLUG con il tuo sottodominio Jamdesk (ad es. acme se la tua documentazione si trova su acme.jamdesk.app).
Se usi un sottopercorso personalizzato dalla dashboard invece del predefinito /docs, sostituisci "/docs" con il tuo sottopercorso in PROXY_PATHS e nel controllo di corrispondenza esatta dentro shouldProxy(). Il flag --path della CLI lo fa quando genera il file, ma solo su un template non modificato. Rigenerare il file sovrascrive le voci personalizzate che hai aggiunto a mano a PROXY_PATHS. Modifica direttamente le voci /docs se hai personalizzato questo Worker.
L'header X-Jamdesk-Forwarded-Host è obbligatorio. Se manca, il fallimento è silenzioso: le richieste continuano ad avere successo, ma le pagine vengono servite con noindex e link canonici che puntano a YOUR_SLUG.jamdesk.app invece che al tuo dominio. I motori di ricerca non indicizzano mai la tua documentazione. Un 403 è il problema opposto: l'header è presente, ma indica un dominio che non è registrato e attivo per questo progetto.
Passaggio 3: configura wrangler.toml
Crea wrangler.toml per configurare il tuo Worker:
name = "docs-proxy"
main = "index.js"
compatibility_date = "2024-01-01"
# Serve only via the routes below, not on the public <name>.workers.dev URL —
# that URL is a second way into the same proxy and is worth closing.
workers_dev = false
# Single catch-all route; the worker handles path filtering internally
routes = [
{ pattern = "yoursite.com/*", zone_name = "yoursite.com" },
]Se il tuo login Cloudflare ha accesso a più di un account, aggiungi anche account_id = "<your account id>". Senza, wrangler deploy si ferma invece di indovinare su quale account effettuare il deploy. npx wrangler whoami elenca i tuoi ID account.
Aggiungi una seconda route se il tuo sito serve traffico anche su www.yoursite.com:
routes = [
{ pattern = "yoursite.com/*", zone_name = "yoursite.com" },
{ pattern = "www.yoursite.com/*", zone_name = "yoursite.com" },
]Passaggio 4: esegui il deploy
Esegui il deploy del Worker su Cloudflare:
npx wrangler deploy
Passaggio 5: verifica
Visita https://yoursite.com/docs e verifica che la documentazione si carichi.
Risoluzione dei problemi
Se hai rinominato il sottopercorso nella dashboard (ad es. /docs → /help) ma PROXY_PATHS del tuo Worker elenca ancora solo /docs, le richieste a /help/* non raggiungono mai Jamdesk. Ricadono in fetch(request) e restituiscono un 404 dal tuo server di origine. Nel frattempo /docs/* continua a funzionare (Jamdesk serve entrambi i prefissi). Per questo il problema è facile da non notare.
Soluzione: aggiungi il nuovo sottopercorso a PROXY_PATHS. Riesegui jamdesk deploy-proxy cloudflare --path <subpath> se il Worker è ancora un template non modificato. Modifica l'array a mano se l'hai personalizzato.
Wrangler dà la precedenza a CLOUDFLARE_API_TOKEN rispetto al login OAuth. Non può avviare un login OAuth mentre quel token è impostato. Questo comando richiede OAuth per elencare le zone del tuo account, quindi si ferma e mostra dove si trova il token invece di fallire dentro wrangler.
Wrangler legge anche il file .env dalla directory in cui lo esegui. Il token può quindi essere impostato per wrangler senza comparire nella tua shell. Un echo $CLOUDFLARE_API_TOKEN vuoto non esclude questa possibilità. Controlla anche se c'è un .env nella directory corrente.
Soluzione: concedi al token account:read e zone:read, poi riesegui. Oppure esegui senza il token:
env -u CLOUDFLARE_API_TOKEN jamdesk deploy-proxy cloudflareenv -u non aiuta quando il token proviene da un .env. Esegui il comando da una directory senza quel .env, oppure sposta temporaneamente il file durante l'esecuzione.
La CLI mostra i domini disponibili prima della selezione della zona. Se vedi "No domains found":
- Verifica di essere loggato con l'account Cloudflare corretto
- Controlla che il tuo dominio sia aggiunto e attivo nella dashboard Cloudflare
- Esegui di nuovo la CLI e seleziona "No" quando ti viene chiesto di continuare con l'account attuale, per cambiare account
Se hai più account Cloudflare:
- Esegui
jamdesk deploy-proxy cloudflare - Quando ti viene chiesto di selezionare un account, scegli quello che contiene il tuo dominio
- Seleziona "Switch to different login" per un login completamente diverso
- La CLI ti disconnette e ti chiede di accedere con le credenziali corrette
Questo errore significa che la zona selezionata non corrisponde al tuo account Cloudflare. Possibili cause:
- Hai selezionato una zona che appartiene a un altro account
- La zona è stata rimossa da Cloudflare
Soluzione: riesegui la CLI e seleziona la zona corretta dall'elenco, oppure passa all'account che possiede la zona.
Usa un pattern di route catch-all: yoursite.com/* (non solo yoursite.com/docs*). La funzione interna shouldProxy() del Worker filtra i percorsi.
Due cause comuni:
- Il Worker non è in esecuzione: imposta il record DNS su Proxied (nuvola arancione) in Cloudflare. I Worker vengono eseguiti solo sui record proxied.
- Header
X-Forwarded-Hostmancante: il Worker deve impostare questo header. Jamdesk lo richiede per generare gli URL corretti degli asset.
Se vedi "Domain is not authorized to serve this content":
- Verifica che il tuo dominio sia registrato nella dashboard Jamdesk
- Completa la verifica DNS (record TXT) per il tuo dominio
- Imposta l'header
X-Jamdesk-Forwarded-Hostnel codice del Worker - Controlla che il tuo dominio sia associato al progetto corretto
Il dominio deve essere verificato prima che il Worker possa servire la documentazione.
I Worker vengono eseguiti solo sui record DNS proxied (nuvola arancione). Se il tuo record A è impostato su "DNS only" (nuvola grigia), le richieste vanno direttamente all'origine e saltano il Worker.
Soluzione: imposta il record A su proxied (nuvola arancione) nel DNS di Cloudflare. Ogni record con una route del Worker deve essere proxied, sottodomini compresi.
Jamdesk verifica la proprietà leggendo direttamente i valori dei tuoi record DNS. Il proxy di Cloudflare (nuvola arancione) nasconde questi valori, quindi la verifica non può completarsi finché è attivo.
Soluzione:
- Imposta il record DNS su DNS only (nuvola grigia)
- Attendi il completamento della verifica (lo stato cambia in active nella dashboard)
- Riattiva Proxied (nuvola arancione) affinché il Worker venga eseguito
Jamdesk serve l'HTML della documentazione con Cache-Control: no-store. Cloudflare non mette in cache le pagine all'edge (cf-cache-status: BYPASS). Ogni richiesta restituisce la versione corrente. Le modifiche pubblicate compaiono senza ritardi di cache.
Gli asset statici sotto /_next/ e /_jd/ (JavaScript, CSS, font, immagini) hanno header di cache immutable a lunga durata. Cloudflare li mette in cache all'edge. I loro nomi di file contengono un hash del contenuto, quindi ogni build produce nuovi URL. Non serve alcuna purge.
cacheEverything: true permette a Cloudflare di mettere in cache questi asset statici sulla route proxied. Non sovrascrive il no-store dell'HTML. Per svuotare la cache dell'edge manualmente, usa Purge Cache di Cloudflare (Caching → Configuration → Purge Everything).
La CLI richiede wrangler 3.0+. Aggiorna con:
npm install -g wrangler@latest