Connection closed with request stream and asynchronous processing

Viewed 122

I have a problem dealing with streams coming from an HTTP request. The handler collects the data from the stream and do some asynchronous stuff before sending the response.

As soon as stream data have been collected, the HTTP connection is closed just before someAsyncStuff is invoked.

This is an example that reproduce the issue. What am I doing wrong?

import * as Busboy from 'busboy'
import * as express from 'express'
import { pipeline } from 'stream'
import concat = require('concat-stream')

const app = express()

app.post('/', (req, res) => {
  const busboy = new Busboy({ headers: req.headers })

  busboy.on('file', (_, file) => {
    pipeline(
      file,
      concat(buffer =>
        someAsyncStuff(buffer.toString())
          .then(length => res.send({ length }))
          .catch(err => res.status(500).send(err.message))
      ),
      err => {
        if (err) res.status(500).send(err.message)
      }
    )
  })

  pipeline(req, busboy, err => {
    if (err) res.status(500).send(err.message)
  })
})

function someAsyncStuff(s: string): Promise<number> {
  return new Promise(resolve => setTimeout(() => resolve(s.length), 1))
}

app.listen('3000')
1 Answers

Using req.pipe seems to work.

import Busboy from 'busboy'
import express from 'express'
import { pipeline } from 'stream'
import concat from 'concat-stream'

const app = express()

app.post('/', (req, res) => {
  const busboy = new Busboy({ headers: req.headers })

  busboy.on('file', (_, file) => {
    pipeline(
      file,
      concat(buffer =>
        someAsyncStuff(buffer.toString())
          .then(length => res.json({ length }))
          .catch(err => res.status(500).send(err.message))
      ),
      err => {
        if (err) res.status(500).send(err.message)
      }
    )
  })
  req.pipe(busboy);
})

function someAsyncStuff(s) {
  return new Promise(resolve => setTimeout(() => resolve(s.length), 1000))
}

app.listen('3000')
Related