Cómo arreglar errores de Discourse Forum /message-bus o Long Polling

1. Problem

When Discourse is configured with a CDN, a common error occurs:

/message-bus/204234de907442e8b77e153786a58e5b/poll
Connection failed / timed out / abnormal status code

Impact:

  • Notifications fail: The red dot (new PM/reply) no longer appears in real time; updates may arrive late or not at all.

  • Real-time updates break: New posts/likes/votes don’t auto-refresh; manual page refresh required.

  • User experience drops: “Connection lost” messages appear; interactions lag.

  • Increased server load: Frontend keeps retrying polls, adding pressure to the origin.

Reason: Discourse uses long polling to maintain real-time communication. Many CDNs enforce default caching, shortened timeouts, challenges/firewall checks, or buffering on long connections, causing interruptions or cached responses that break real-time behavior.


2. General Approach (Stability First)

  • Domain separation: Route MessageBus through a dedicated domain that connects directly to the origin.

  • Reverse proxy (Nginx) layer:

    • Enable CORS for /message-bus.

    • Disable proxy buffering, relax timeouts, explicitly forbid caching.

  • CDN layer (if still used):

    • Configure /message-bus/* with no caching, extended timeout, no JS challenges/CAPTCHA/rate limiting, and cookie/authorization passthrough.

    • Or bypass CDN entirely.


3. Implementation Steps

1) Configure Discourse Environment Variables

Edit app.yml (usually at /var/discourse/containers/app.yml) and add/modify under env::

env:
  DISCOURSE_MESSAGE_BUS_REDIS_ENABLED: true
  DISCOURSE_LONG_POLLING_BASE_URL: "https://messagebus.example.com"

Apply changes (official deployment):

cd /var/discourse
./launcher rebuild app

Explanation:

  • DISCOURSE_LONG_POLLING_BASE_URL tells the frontend to use the MessageBus domain.

  • REDIS_ENABLED should remain enabled.


2) DNS & Certificate

  • Point messagebus.example.com directly to the origin, bypassing CDN (best practice).

  • Set up a valid HTTPS certificate for the domain.


3) Nginx (MessageBus domain) Reverse Proxy & CORS

Add or update the following in the server block for messagebus.example.com:

location ^~ /message-bus {

    # (1) Handle CORS preflight (OPTIONS)
    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) Reverse proxy to Discourse
    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    # or, if standalone:
    # proxy_pass http://127.0.0.1:3000;

    # (3) Prevent duplicate CORS headers
    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) Normal CORS for requests
    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) Long polling stability settings
    proxy_read_timeout    120s;
    proxy_send_timeout    120s;
    proxy_connect_timeout 60s;

    proxy_buffering off;
    add_header X-Accel-Buffering no always;

    # (6) Explicitly forbid caching
    add_header Cache-Control "no-store, no-cache, must-revalidate" always;
}

:warning: Security note: If Access-Control-Allow-Credentials: true is used, Origin must not be *; it must match the exact forum domain.


4) CDN Rules (if forum still behind CDN)

Recommended: set no cache + extended timeout + bypass WAF/rate-limiting for these paths:

Regex example:

^/(session|login|message-bus|admin|u|users)(/|$)

Policy:

  • No browser/node caching (no-store/no-cache).

  • Upstream/read/idle timeout ≥ 60–120s.

  • Disable JS challenge/CAPTCHA/bot management.

  • Pass through cookies & Authorization headers (do not strip).


4. How to Verify Success

1) Browser DevTools → Network

On the forum page:

  • Observe /message-bus/…/poll.

  • Request should “hang” for ~20–60s, then return 200 (possibly empty).

  • Next poll request is triggered automatically.

Check response headers:

  • Access-Control-Allow-Origin: https://bbs.example.com

  • Cache-Control: no-store

  • No Age, X-Cache: HIT, or CF-Cache-Status: HIT (means not cached).

Common issues:

  • Fixed 10s/30s errors → edge/origin timeout.

  • 504/524: timeout.

  • 499: intermediate layer disconnect.

  • 403/401: WAF/auth blocking.


2) Command-Line Quick Probe (optional)

Check connectivity & headers (not full polling):

curl -I "https://messagebus.example.com/message-bus/health-check" \
  -H "Origin: https://bbs.example.com"

Note: Actual polls require session context; this only verifies CORS & connectivity.

1 me gusta