1. Problème
Lorsqu’il est configuré avec un CDN, Discourse rencontre une erreur courante :
/message-bus/204234de907442e8b77e153786a58e5b/poll
Échec de la connexion / délai dépassé / code d'état anormal
Impact :
-
Les notifications échouent : Le point rouge (nouveau message privé/réponse) n’apparaît plus en temps réel ; les mises à jour peuvent arriver en retard ou pas du tout.
-
Les mises à jour en temps réel se cassent : Les nouveaux messages/j’aime/votes ne se rafraîchissent pas automatiquement ; un rafraîchissement manuel de la page est nécessaire.
-
L’expérience utilisateur se dégrade : Des messages “Connexion perdue” apparaissent ; les interactions sont ralenties.
-
Charge accrue sur le serveur : Le frontend continue de réessayer les sondages, ajoutant une pression sur l’origine.
Raison : Discourse utilise le “long polling” pour maintenir la communication en temps réel. De nombreux CDN appliquent une mise en cache par défaut, des délais d’expiration raccourcis, des vérifications de défis/pare-feu ou une mise en mémoire tampon sur les connexions longues, provoquant des interruptions ou des réponses mises en cache qui brisent le comportement en temps réel.
2. Approche Générale (Stabilité d’abord)
-
Séparation des domaines : Acheminer MessageBus via un domaine dédié qui se connecte directement à l’origine.
- Domaine du forum (via CDN) : https://bbs.example.com
- Domaine MessageBus (sans CDN) : https://messagebus.example.com
-
Couche de proxy inverse (Nginx) :
- Activer CORS pour /message-bus.
- Désactiver la mise en mémoire tampon du proxy, assouplir les délais d’expiration, interdire explicitement la mise en cache.
-
Couche CDN (si toujours utilisée) :
- Configurer /message-bus/* avec aucune mise en cache, délai d’expiration prolongé, aucun défi JS/CAPTCHA/limitation de débit, et passage des cookies/authentification.
- Ou contourner complètement le CDN.
3. Étapes d’Implémentation
1) Configuration des variables d’environnement Discourse
Modifiez app.yml (généralement dans /var/discourse/containers/app.yml) et ajoutez/modifiez sous env::
env:
DISCOURSE_MESSAGE_BUS_REDIS_ENABLED: true
DISCOURSE_LONG_POLLING_BASE_URL: "https://messagebus.example.com"
Appliquez les modifications (déploiement officiel) :
cd /var/discourse
./launcher rebuild app
Explication :
- DISCOURSE_LONG_POLLING_BASE_URL indique au frontend d’utiliser le domaine MessageBus.
- REDIS_ENABLED doit rester activé.
2) DNS et Certificat
- Pointez messagebus.example.com directement vers l’origine, en contournant le CDN (meilleure pratique).
- Configurez un certificat HTTPS valide pour le domaine.
3) Nginx (domaine MessageBus) Proxy Inverse et CORS
Ajoutez ou mettez à jour ce qui suit dans le bloc server pour messagebus.example.com :
location ^~ /message-bus {
# (1) Gérer le pré-vol OPTIONS de CORS
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' 'https://bbs.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,discourse-deferred-track-view-topic-id,discourse-present,discourse-track-view,discourse-deferred-track-view,x-silence-logger,dont-chunk,x-shared-session-key' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=UTF-8' always;
add_header 'Content-Length' 0 always;
return 204;
}
# (2) Proxy inverse vers Discourse
proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
# ou, si autonome :
# proxy_pass http://127.0.0.1:3000;
# (3) Empêcher les en-têtes CORS dupliqués
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Credentials;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Max-Age;
# (4) CORS normal pour les requêtes
add_header 'Access-Control-Allow-Origin' 'https://bbs.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With,discourse-deferred-track-view-topic-id,discourse-present,discourse-track-view,discourse-deferred-track-view,x-silence-logger,dont-chunk,x-shared-session-key' always;
# (5) Paramètres de stabilité du long polling
proxy_read_timeout 120s;
proxy_send_timeout 120s;
proxy_connect_timeout 60s;
proxy_buffering off;
add_header X-Accel-Buffering no always;
# (6) Interdire explicitement la mise en cache
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
}
Note de sécurité : Si Access-Control-Allow-Credentials: true est utilisé, l’origine ne doit pas être \* ; elle doit correspondre au domaine exact du forum.
4) Règles CDN (si le forum est toujours derrière un CDN)
Recommandé : définir pas de cache + délai d’expiration prolongé + contournement WAF/limitation de débit pour ces chemins :
Exemple d’expression régulière :
^/(session|login|message-bus|admin|u|users)(/|$)
Politique :
- Pas de mise en cache par le navigateur/nœud (no-store/no-cache).
- Délai d’expiration amont/lecture/inactif ≥ 60–120s.
- Désactiver le défi JS/CAPTCHA/gestion des bots.
- Transmettre les cookies et les en-têtes d’autorisation (ne pas supprimer).
4. Comment vérifier le succès
1) Outils de développement du navigateur → Réseau
Sur la page du forum :
- Observez
/message-bus/.../poll. - La requête doit “pendre” pendant environ 20 à 60 secondes, puis retourner 200 (éventuellement vide).
- La requête de sondage suivante est déclenchée automatiquement.
Vérifiez les en-têtes de réponse :
- Access-Control-Allow-Origin: https://bbs.example.com
- Cache-Control: no-store
- Pas d’âge, X-Cache: HIT, ou CF-Cache-Status: HIT (signifie non mis en cache).
Problèmes courants :
- Erreurs fixes de 10s/30s → délai d’expiration du bord/de l’origine.
- 504/524 : délai d’expiration.
- 499 : déconnexion de la couche intermédiaire.
- 403/401 : blocage WAF/authentification.
2) Sonde rapide en ligne de commande (facultatif)
Vérifiez la connectivité et les en-têtes (pas de sondage complet) :
curl -I "https://messagebus.example.com/message-bus/health-check" \
-H "Origin: https://bbs.example.com"
Note : Les sondages réels nécessitent un contexte de session ; ceci vérifie uniquement CORS et la connectivité.