Servir un centre d’aide avec des ressources statiques

CloudflareBeginner
Pratiquer maintenant

Introduction

Un centre d’aide doit fournir rapidement des pages publiques, un point de terminaison JSON de vérification de l’état et un document réservé au personnel. Un fichier statique peut prendre accidentellement la priorité sur le code prévu pour traiter une requête. Vous observerez ce comportement en local, configurerez un routage donnant la priorité au Worker, puis déploierez une politique explicite qui conserve un site public fonctionnel tout en protégeant une ressource de personnel synthétique.

Ce laboratoire autonome démarre dans /home/labex/project/help-center avec Node.js 22.22.0, Wrangler 4.131.1 installé dans le projet et des ressources HTML/CSS/JavaScript fournies. Utilisez votre propre compte Cloudflare de formation ainsi que les compétences d’autorisation, de déploiement et de gestion des fichiers secrets vues précédemment. Aucune VM précédente, aucune ressource cloud, aucun domaine acheté, aucune base de données ni aucune mise à niveau payante ne sont nécessaires. Les requêtes sont comptabilisées dans l’utilisation normale du compte.

Tout le contenu et tous les identifiants sont synthétiques. Gardez un terminal ouvert. La configuration initiale non sûre reste locale ; seul le Worker corrigé est déployé. Supprimez le déploiement, effacez l’identifiant de test local et déconnectez-vous avant de terminer la VM.

Observer localement le routage donnant la priorité aux ressources

Dans cette étape, vous allez examiner une structure de centre d’aide fournie et observer comment les fichiers correspondants prennent par défaut la priorité sur un Worker. Les ressources contiennent volontairement un fichier /api/health en conflit ainsi qu’un faux manuel du personnel. Tout est synthétique et cette première configuration reste locale.

cd /home/labex/project/help-center
node --version
npx wrangler --version
ls -R public

Vous devez obtenir Node v22.22.0 et Wrangler 4.131.1. La configuration a installé les outils locaux au projet ; pour reproduire cette configuration ailleurs, utilisez npm ci avec le fichier de verrouillage du projet. Le répertoire public contient le HTML, le CSS, le JavaScript exécuté dans le navigateur et les deux ressources utilisées pour le routage. N’y placez jamais d’identifiants ni de vrais documents internes.

WORKER_NAME="labex-help-$(openssl rand -hex 6)"
cat > wrangler.jsonc <<CONFIG
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-09-14",
  "workers_dev": true,
  "preview_urls": false,
  "assets": {
    "directory": "./public",
    "binding": "ASSETS",
    "html_handling": "none",
    "not_found_handling": "none",
    "run_worker_first": false
  }
}
CONFIG

directory sélectionne les fichiers à téléverser, tandis que binding les expose au gestionnaire via env.ASSETS. html_handling: none conserve les chemins de fichiers explicites ; not_found_handling: none évite une redirection automatique vers une application monopage (SPA). Le gestionnaire associe explicitement / à /index.html, car la gestion automatique du HTML est désactivée. Il prévoit de renvoyer du JSON pour l’état de santé et de déléguer les autres chemins au stockage des ressources.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    if (new URL(request.url).pathname === '/api/health') {
      return Response.json({status: 'ok', service: 'help-center'});
    }
    const assetUrl = new URL(request.url);
    if (assetUrl.pathname === '/') assetUrl.pathname = '/index.html';
    return env.ASSETS.fetch(new Request(assetUrl, request));
  }
};
JS
npx wrangler dev --ip 0.0.0.0 --port 8080 > dev.log 2>&1 &
cat dev.log

Attendez que le journal indique que le serveur est prêt avant de continuer ; réexécutez cat si nécessaire.

curl -i http://127.0.0.1:8080/
curl -i http://127.0.0.1:8080/styles.css
curl -i http://127.0.0.1:8080/api/health
curl -i http://127.0.0.1:8080/staff/handbook.html

La page d’accueil et le CSS renvoient 200. L’état de santé renvoie le texte statique STATIC_HEALTH_PLACEHOLDER, et non le JSON du gestionnaire, car la ressource correspondante est prioritaire. Le manuel synthétique est également lisible directement. Cela démontre la priorité du routage, et non un déploiement sûr. Ne déployez pas cette configuration initiale. Utilisez la vérification avant de la modifier.

Si votre laboratoire propose un aperçu Web sur le port 8080, ouvrez-le maintenant. La structure du centre d’aide se charge, mais sa ligne d’état indique que l’état de l’API est indisponible, car le navigateur attendait du JSON. Considérez les réponses de la ligne de commande comme la référence pour vérifier le routage ; l’aperçu sert de contrôle visuel.

L’exemple ci-dessous montre le problème initial : la page et la feuille de style se chargent, mais API status unavailable signifie que le navigateur n’a pas reçu le JSON d’état de santé attendu. Le simple chargement de la structure de la page ne confirme pas que le routage de l’API fonctionne.

Centre d’aide avant la correction du routage, avec API status unavailable

Exécuter le Worker avant les ressources et protéger le contenu du personnel

Dans cette étape, vous allez exécuter le gestionnaire avant toute correspondance avec une ressource statique. Arrêtez le processus de développement réel indiqué par jobs ; l’exemple suppose qu’il s’agit du processus 1.

jobs
kill %1
cat > wrangler.jsonc <<CONFIG
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-09-14",
  "workers_dev": true,
  "preview_urls": false,
  "assets": {
    "directory": "./public",
    "binding": "ASSETS",
    "html_handling": "none",
    "not_found_handling": "none",
    "run_worker_first": true
  }
}
CONFIG

Avec run_worker_first: true, chaque requête passe par le gestionnaire, y compris celles qui correspondraient autrement directement à un fichier. Des modèles de routes sélectives existent également, mais cette petite application utilise une seule politique de routage explicite. Consultez Static Assets configuration.

Générez un identifiant de personnel temporaire en utilisant la procédure de fichier secret vue précédemment. umask restreint les permissions des nouveaux fichiers. Il s’agit d’un jeton porteur réservé au laboratoire, et non d’un jeton d’API de compte. Conservez-le hors des fichiers publics, du JavaScript exécuté dans le navigateur, des URL et des journaux.

umask 077
STAFF_TOKEN=$(openssl rand -hex 24)
printf 'STAFF_TOKEN=%s\n' "$STAFF_TOKEN" > .dev.vars
cat .gitignore

Vérifiez que .dev.vars* et .env* sont ignorés. Remplacez le gestionnaire par la politique complète ci-dessous. Elle décode le chemin une seule fois, renvoie l’état de santé au format JSON, n’autorise que les fichiers publics listés, vérifie l’identifiant du personnel avant de récupérer cette ressource et rejette les chemins inconnus. La requête envoyée à ASSETS ne contient aucun en-tête Authorization du client. Les réponses protégées utilisent private, no-store.

cat > src/index.js <<'JS'
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    let path;
    try { path = decodeURIComponent(url.pathname); }
    catch { return Response.json({error: 'not_found'}, {status: 404}); }
    if (path === '/api/health') {
      if (request.method !== 'GET') {
        return Response.json({error: 'method_not_allowed'}, {status: 405, headers: {Allow: 'GET'}});
      }
      return Response.json({status: 'ok', service: 'help-center'});
    }
    const publicPaths = ['/', '/index.html', '/styles.css', '/app.js'];
    if (path === '/staff/handbook.html') {
      if (!env.STAFF_TOKEN) return Response.json({error: 'staff_unconfigured'}, {status: 503});
      if (request.headers.get('Authorization') !== `Bearer ${env.STAFF_TOKEN}`) {
        return Response.json({error: 'unauthorized'}, {status: 401});
      }
    } else if (!publicPaths.includes(path)) {
      return Response.json({error: 'not_found'}, {status: 404});
    }
    if (!['GET', 'HEAD'].includes(request.method)) {
      return Response.json({error: 'method_not_allowed'}, {status: 405, headers: {Allow: 'GET, HEAD'}});
    }
    url.pathname = path === '/' ? '/index.html' : path;
    // Only known paths reach the asset store, after any required authorization.
    const response = await env.ASSETS.fetch(new Request(url, {method: request.method}));
    if (path === '/staff/handbook.html') {
      const headers = new Headers(response.headers);
      headers.set('Cache-Control', 'private, no-store');
      return new Response(response.body, {status: response.status, headers});
    }
    return response;
  }
};
JS
npx wrangler dev --ip 0.0.0.0 --port 8080 > dev.log 2>&1 &
cat dev.log

Une fois que le serveur est prêt, comparez les réponses publiques, protégées et inconnues :

curl -i http://127.0.0.1:8080/api/health
curl -i http://127.0.0.1:8080/staff/handbook.html
curl -i http://127.0.0.1:8080/staff/handbook.html -H "Authorization: Bearer wrong-token"
curl -i http://127.0.0.1:8080/staff/handbook.html -H "Authorization: Bearer $STAFF_TOKEN"
curl -i --path-as-is http://127.0.0.1:8080/%73taff/handbook.html
curl -i http://127.0.0.1:8080/missing-page -H "Sec-Fetch-Mode: navigate"

L’état de santé renvoie désormais 200 avec {"status":"ok","service":"help-center"}, même si le fichier en conflit existe toujours. Des identifiants absents ou incorrects renvoient du JSON avec le statut 401 ; l’identifiant correspondant renvoie le HTML du manuel synthétique. Le chemin du personnel encodé renvoie également 401, et la navigation vers un chemin inconnu renvoie du JSON avec le statut 404. Supprimer la ressource masquerait le problème de routage ; conservez-la.

Actualisez l’aperçu Web facultatif sur le port 8080 : l’état doit maintenant indiquer API status: ok. Le point de terminaison du manuel renvoie du JSON avec le statut 401 sans identifiant. Certains navigateurs intégrés bloquent la navigation vers cette réponse et laissent la page précédente affichée ; utilisez le résultat de curl ci-dessus pour l’examiner. Ce comportement du navigateur ne prouve pas que l’accès a réussi. Utilisez curl avec l’en-tête synthétique pour un accès autorisé ; ne collez pas le secret dans la barre d’adresse. Effectuez la vérification avec le serveur en cours d’exécution. Elle vérifie également HEAD, les chemins encodés, les variantes d’écriture et les types de ressources publiques.

Comparez la ligne d’état avec celle de l’aperçu précédent. API status: ok indique désormais que la page peut lire la réponse d’état de santé. Ce contrôle visuel couvre la route publique d’état de santé ; utilisez les réponses curl ci-dessus pour évaluer le manuel protégé.

Centre d’aide après la correction du routage, avec API status ok

Déployer les ressources et le gestionnaire protégé

Dans cette étape, vous allez déployer uniquement la configuration corrigée sur votre compte de formation. Arrêtez le processus local actuel en utilisant son numéro réel indiqué par jobs.

jobs
kill %1
npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_tail:read

Suivez dans votre navigateur connecté le lien et le code affichés, examinez les autorisations Wrangler existantes et l’accès en arrière-plan, puis sélectionnez votre compte de formation. Attendez la fin de l’opération dans le terminal.

npx wrangler whoami --json

Confirmez le nom et l’identifiant réels du compte, puis remplacez YOUR_ACCOUNT_ID ci-dessous par cet identifiant. Conservez le nom de ressource initial et les paramètres corrigés des ressources.

cat > wrangler.jsonc <<CONFIG
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-09-14",
  "account_id": "YOUR_ACCOUNT_ID",
  "workers_dev": true,
  "preview_urls": false,
  "assets": {
    "directory": "./public",
    "binding": "ASSETS",
    "html_handling": "none",
    "not_found_handling": "none",
    "run_worker_first": true
  }
}
CONFIG
npx wrangler deploy

Wrangler téléverse le répertoire public et déploie son gestionnaire. Copiez ci-dessous l’URL exacte workers.dev affichée. Réutilisez le sous-domaine existant du compte de formation ; les nouveaux utilisateurs peuvent suivre l’invite de Wrangler concernant le sous-domaine disponible.

APP_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$APP_URL/staff/handbook.html"

Avant le téléversement du secret, cette route renvoie 503 staff_unconfigured : le gestionnaire s’exécute en premier et applique un refus par défaut. .dev.vars est une configuration locale et n’a pas été téléversé lors du déploiement. Si la propagation initiale du nom d’hôte retarde une réponse, réessayez brièvement avant d’analyser une erreur persistante.

npx wrangler secret bulk .dev.vars
npx wrangler secret list

Confirmez que STAFF_TOKEN apparaît comme secret_text, sans afficher sa valeur. Le déploiement du secret peut prendre un court instant avant d’atteindre tous les points de service. Si les requêtes suivantes renvoient encore staff_unconfigured, attendez 10 secondes puis répétez-les pendant deux minutes au maximum. Exigez un résultat stable avec 401 sans identifiant et 200 avec identifiant avant d’effectuer la vérification. Une différence persistante doit être analysée ; n’acceptez pas 503 comme résultat final et ne modifiez pas la politique d’autorisation pour faire réussir un contrôle.

curl -i "$APP_URL/"
curl -i "$APP_URL/api/health"
curl -i "$APP_URL/staff/handbook.html"
curl -i "$APP_URL/staff/handbook.html" -H "Authorization: Bearer $STAFF_TOKEN"
curl -i "$APP_URL/missing-page" -H "Sec-Fetch-Mode: navigate"

Vous devez obtenir du HTML public, du JSON pour l’état de santé, 401 sans identifiant, le HTML du manuel avec l’identifiant et 404 pour la page inconnue. Dans le même compte du Dashboard, ouvrez Compute → Workers & Pages, localisez le Worker exact et confirmez son URL publique. Utilisez la vérification pour confirmer la propriété réelle, les liaisons déployées, le contenu des ressources et le comportement d’autorisation. Vous pouvez également ouvrir la page d’accueil publique dans votre propre navigateur ; n’envoyez pas le jeton du personnel dans une URL. La protection par jeton synthétique illustre le routage, mais ne constitue pas un système complet d’identité du personnel.

Dans l’onglet Overview du Worker, comparez le nom affiché dans le fil d’Ariane et l’adresse workers.dev liée avec la sortie de votre déploiement. Le nom et le sous-domaine de cette capture sont des exemples ; le nom généré et le sous-domaine de votre compte seront différents. Il s’agit de l’adresse publique déployée, tandis que Web 8080 prévisualise votre serveur de développement local. Ouvrir ce Worker existant ne nécessite pas de créer une autre application.

Worker du centre d’aide déployé et son adresse publique dans Overview

Supprimer le déploiement du centre d’aide

Dans cette étape, vous allez supprimer le Worker du laboratoire, ainsi que ses ressources et sa liaison secrète, tout en étant encore autorisé. Confirmez le nom unique et le compte :

cat wrangler.jsonc
npx wrangler delete

Vérifiez le nom exact du laboratoire à l’invite, puis appuyez sur la touche y. Wrangler 4.131.1 peut signaler l’erreur d’authentification documentée et héritée de Workers Sites concernant KV après la suppression. N’élargissez pas les autorisations et n’utilisez pas ce message comme preuve de suppression. Actualisez Workers & Pages et utilisez la vérification : un inventaire autorisé réussi doit montrer que ce nom est absent. Préservez les ressources sans rapport, le compte et son sous-domaine workers.dev.

Supprimer l’identifiant local et se déconnecter

Dans cette étape, vous allez supprimer l’identifiant synthétique local après avoir vérifié le nettoyage cloud, puis déconnecter cette VM.

rm .dev.vars
unset STAFF_TOKEN
npx wrangler logout
npx wrangler whoami --json

Vous devez obtenir explicitement "loggedIn": false ; un code de sortie non nul indiquant l’absence d’authentification est attendu lorsque ce résultat structuré est présent. Utilisez la vérification, puis terminez la VM. La session de connexion du navigateur peut rester disponible ; ni l’arrêt de la VM ni la déconnexion ne suppriment les ressources cloud à votre place.

Résumé

Vous avez observé un routage donnant la priorité aux ressources, puis utilisé l’exécution du Worker en premier pour faire passer les réponses d’API et l’autorisation avant les fichiers correspondants. La structure de centre d’aide fournie a conservé le HTML public, le CSS et le JavaScript exécuté dans le navigateur, tandis que la gestion explicite des chemins bloquait les requêtes non authentifiées vers le personnel et les routes inconnues. Vous avez testé les chemins encodés et la navigation de type navigateur, déployé le site corrigé avec un téléversement séparé du secret, puis vérifié la suppression et la déconnexion.

Choisissez délibérément l’ordre du routage lorsque des fichiers statiques et une politique applicative partagent un nom d’hôte. Une réponse locale seule ne prouve ni la configuration déployée ni l’identité du compte.