node.jsreactjsexpressserver-sent-eventsnode-http-proxy

Proxy EventSource (SSE) connections through NodeJS to a localhost backend


I have an issue with EventSource connections through node-http-proxy v1.18.1. The connections work in development, from create-react-app, proxy: , but when deploying to production, the connection fails with the following browser (chromium) error:

EventSource's response has a MIME type ("text/html") that is not "text/event-stream". Aborting the connection.

The portion of my server.js that creates the proxy is:

const httpProxy = require('http-proxy');

var app = express();
var apiProxy = httpProxy.createProxyServer({secure: false});

app.use(express.static(root));
app.use(compression());

/* proxy api calls over to port 9047 */
app.all('/api/*', (req, res) => {
   apiProxy.web(req,res, { target: 'https://localhost:9047' });
});

and the HTML document that React/NodeJS appears to be returning to the browser instead of the EventStream data is:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <link rel="icon" href="/icons/favicon.ico"/>
        <meta name="viewport" content="width=device-width,initial-scale=1"/>
        <meta name="theme-color" content="#000000"/>
        <meta name="description" content="Web site created using create-react-app"/>
        <link rel="apple-touch-icon" href="/icons/threaded_icon_57x57.png"/>
        <link rel="manifest" href="/manifest.json"/>
        <title>My App</title>
        <script defer="defer" src="/static/js/main.8ebfafc7.js"></script>
        <link href="/static/css/main.8c23b3de.css" rel="stylesheet">
    </head>
    <body>
        <noscript>You need to enable JavaScript to run this app.</noscript>
        <div id="root"></div>
    </body>
</html>

I have also tried using the http-proxy-middleware library, which wraps the node-http-proxy module. Same exact results.

The backend server (springboot) on localhost does not appear to be receiving the call. It appears to be not proxying correctly within NodeJS/Express.

I am 100% sure that my backend (springboot) server is returning the correct response type because it works in dev, and it works in production using a non-React/non-express client. Any suggestions?


Solution

  • The root issue had to do with the URL path for the event stream registration being different than the pattern matched in the express .all() call.