Search code examples
javascriptnode.jsreactjsexpressserver-sent-events

Client not receiving Server Sent Events from Express.js server


I have a Next.js (React) client that I've setup to listen to Server-Sent Events from my Node.js/Express.js server, but it doesn't seem to be receiving messages for some reason.

The open and error events of EventSource are working properly, but whenever I use .onmessage it doesn't detect anything.

What am I doing wrong?

Express.js Code:

router.get('/stream/:walletAddress', async (req, res, next) => {
    try {
        res.set({
            Connection: 'keep-alive',
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Access-Control-Allow-Origin': '*'
        });
        res.flushHeaders();

        let x = 0;
        const id = setInterval(() => {
            res.write(`event: message\n`);
            res.write(`data: ${x++}\n\n`);
        }, 2000);

        res.on('close', () => {
            console.log('Client closed.');
            clearInterval(id);
        });
    } catch (err) {
        next(err);
    }
});

Next.js (React) Code:

import { API_URL } from 'config';
import { useWalletStore } from 'src/stores';


export const FetchTxsProvider = ({ children }) => {
    const safeSdkReader = useWalletStore(state => state.safeSdkReader);

    useEffect(() => {
        const eventSource = new EventSource(
            `${API_URL}/transactions/stream/${safeSdkReader.getAddress()}`
        );

        eventSource.onopen = function (e) {
            console.log('Successfully connected.');
        };

        eventSource.onerror = function (err) {
            console.error(err);
            eventSource.close();
        };

        // ! Should fire here but doesn't!
        eventSource.onmessage = function (event) {
            console.log('Event: ', event);
        };

        return () => {
            console.log('Connection closed.');
            eventSource.close();
        };
    }, [safeSdkReader]);

    return <>{children}</>
};


Solution

  • Don't know why, but the headers were missing 'Content-Encoding': 'none'.

    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',          
      'Content-Encoding': 'none',
      'Connection': 'keep-alive',
      'Access-Control-Allow-Origin': '*'
    });