question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Server-Sent Events don't work in Next API routes

See original GitHub issue

Bug report

Describe the bug

When using Next’s API routes, chunks that are written with res.write aren’t sent until after res.end() is called.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create the following API route in a Next app:
export default async (req, res) => {
  let intervalID = null

  res.setHeader('Content-Type', 'text/event-stream')
  res.write('data: CONNECTION ESTABLISHED\n')

  const end = () => {
    if (intervalID) {
      clearTimeout(intervalID)
    }
  }

  req.on('aborted', end)
  req.on('close', end)

  const sendData = () => {
    const timestamp = (new Date).toISOString()
    res.write(`data: ${timestamp}\n`)
  }

  intervalID = setInterval(sendData, 1000)
}
  1. Connect to the route with a tool that supports Server-Sent Events (i.e. Postwoman).

Expected behavior

The route sends a new event to the connection every second.

Actual behavior

The route doesn’t send any data to the connection unless a call to res.end() is added to the route.

System information

  • OS: macOS
  • Version of Next.js: 9.1.5

Additional context

When using other HTTP frameworks (Express, Koa, http, etc) this method works as expected. It’s explicitly supported by Node’s http.incomingMessage and http.ServerResponse classes which, from what I understand, Next uses as a base for the req and res that are passed into Next API routes.

I’d hazard a guess that #5855 was caused by the same issue, but considered unrelated because the issue was obscured by the express-sse library.

There are also two Spectrum topics about this (here and here) that haven’t garnered much attention yet.

Supporting Websockets and SSE in Next API routes may be related, but fixing support for SSE should be a lower barrier than adding support Websockets. All of the inner workings are there, we just need to get the plumbing repaired.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:28 (3 by maintainers)

github_iconTop GitHub Comments

13reactions
trezycommented, Apr 16, 2020

Thanks for all the effort on this ticket, folx! I wanted to pop in and say I think we can mark it as resolved. Here’s a quick TL;DR:

  • SSE does work in Next.js API routes, you just have to manage the compression as mentioned by @ijjk and demonstrated by @wenerme.
  • Even though SSE is supported in Next.js, it’s probably not supported in serverless environments. Specifically, I can confirm that it won’t work on Now or Netlify.
  • A better solution for adding SSE to your app would be to leverage something like Pusher.com, or to create a separate API hosted on Heroku or some other system that supports streams.
13reactions
wenermecommented, Feb 18, 2020

Code from above comment, if you want to try

import {NextApiRequest, NextApiResponse} from 'next'

export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// curl -Nv localhost:3000/api/see
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
  res.setHeader('Cache-Control', 'no-cache, no-transform');
  res.setHeader('X-Accel-Buffering', 'no');

  for (let i = 0; i < 5; i++) {
    res.write(`data: Hello seq ${i}\n\n`);
    await sleep(1000);
  }
  res.end('done\n');
};

export default handler;
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to use server-sent-events in express.js - Stack Overflow
IO to implement basic Server-Sent Events. The browser API is dead simple and the implementation in Express requires only a couple of changes...
Read more >
Using Fetch Event Source for server-sent events in React
Let's explore the principles of server-sent events by focusing on a specifically designed open package: Fetch Event Source.
Read more >
Developing Real-Time Web Applications with Server-Sent ...
Learn how to create real-time web applications by using the Server-Sent Events specification.
Read more >
Server Sent Events are still not production ready after a ...
The problem with SSE ... The issue is this. SSE opens a stream to the client with no content length and sends packets...
Read more >
Comparing WebSockets and Server-Sent Events | Ably Blog
EventSource accepts an HTTP event stream connection from a specific URL and keeps the connection open while retrieving available data. Server- ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found