skip to Main Content

It is possible on Express.js to send a response in chunk of data? I have tried (online demo):

const express = require('express');
const app = express();
const port = 3111;

const sleep = (ms) => {
  return new Promise((resolve) => setTimeout(resolve, ms));
};

app.get('/', async (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  // flush to enable stream
  res.flushHeaders();
  res.write('[');
  for (let i = 1; i <= 1000; i++) {
    res.write(JSON.stringify(`data ${i}`));
    if (i + 1 <= 1000) {
      res.write(',');
    }
    await sleep(1);
  }
  res.write(']');
  res.end();
});

app.listen(port, () => {
  console.log(`App is live at http://localhost:${port}`);
});

But both on Google Chrome and Postman, the response is showed only when res.end() is called

2

Answers


  1. There are some considerations

    1. You should add a correct Content-Type for streams such as application/stream+json
    2. Keep in mind that browsers and some HTTP clients may buffer the respond (they will not display the chunks as they arrive but instead wait until they receive the entire response), so you may need to consider using javascript to handle the response.
    3. You don’t need res.flushHeaders() as Express automatically handle it when you start writing the response body
    import express from "express";
    const app = express();
    
    const sleep = (ms) => {
        return new Promise((resolve) => setTimeout(resolve, ms));
    };
    
    app.get('/stream', async (_req, res) => {
        res.setHeader('Content-Type', 'application/stream+json');
    
        res.write('[');
        for (let i = 1; i <= 1000; i++) {
            res.write(JSON.stringify(`data ${i}`));
            if (i < 1000) {
                res.write(",");
            }
            await sleep(1); // Simulates a delay
        }
        res.write(']');
        res.end();
    });
    
    const port = 3000;
    app.listen(port, () => {
        console.log(`Server running on http://localhost:${port}`);
    });
    
    Login or Signup to reply.
  2. Using netcat, the pacing of data returned seems correct, and it’s chunk encoded.

    echo -ne 'GET /stream HTTP/1.1nn' | netcat localhost 8080
    

    Sample of output:

    HTTP/1.1 200 OK
    X-Powered-By: Express
    Content-Type: application/json
    Date: Mon, 06 May 2024 08:58:26 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    Transfer-Encoding: chunked
    
    1
    [
    8
    "data 1"
    1
    ,
    8
    "data 2"
    1
    ,
    8
    "data 3"
    1
    ,
    8
    "data 4"
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search