7

I have this basic express app:

var express = require('express');
var app = express();
var PORT = 3000;
var through = require('through');


function write(buf) {
    console.log('writing...');
    this.queue('okkkk');
}

function end() {
    this.queue(null);
}

var str = through(write, end);


/* routes */
app.get('/', function(req, res){
    res.send("Hello!");
})


app.post('/stream', function(req, res){
    var s = req.pipe(str).pipe(res);
    s.on('finish', function() {
       console.log('all writes are now complete.'); // printed the first time
    });
});


/* listen */
app.listen(PORT, function () {
    console.log('listening on port ' + PORT + '...');
});

When I post some data to /stream endpoint for the first time after starting the server I get okkk as the response which is what I expect. However, after that, any requests to /stream endpoint just timeout and not return any response.

Why is it so? What's exactly happening here?

Jatin
  • 14,112
  • 16
  • 49
  • 78
  • You're piping the request, but you still have to answer the request with a response, or at least end it with `res.end()` otherwise it stays open until it time outs. – adeneo Mar 02 '15 at 20:52
  • Isn't `end()` needed only when I call `.write()` explicitly? I tried it anyway, and now with it I get an empty response. Also, why would it work the first time after starting the server if I needed `.end()` ? – Jatin Mar 02 '15 at 20:57
  • Well, for some reason the response isn't finished and it's kept open, I'm not sure why, I've never seen anyone pipe the request before, and that could be it. – adeneo Mar 02 '15 at 21:01
  • Well, request is a readable stream, so I think you can certainly pipe it. – Jatin Mar 02 '15 at 21:17
  • You can pipe it, but you have to end it, and you have to send a response and close everything, otherwise it's kept in limbo, I just don't know how to do this when piping the entire request, maybe someone else does ? – adeneo Mar 02 '15 at 21:22
  • Yeah, the 'finish' event on response stream is never fired after the first time. I think that probably because the `end` event on request is never called. (However, it all works the first time). Edited the question details to reflect this. – Jatin Mar 02 '15 at 21:42

2 Answers2

13

I had this same problem and looks like res was not being finished properly. So I added a callback to my stream and ended que res myself. That fixed my problem:

stream.on('end', () => res.end());
stream.pipe(res);
Sergio
  • 28,539
  • 11
  • 85
  • 132
  • This approach was actually breaking my code and I was getting empty response instead of a streamed image. – yuranos Nov 30 '20 at 22:24
  • @yuranos what did you replace it with? – Sergio Nov 30 '20 at 22:47
  • It just works for me. I don't have the issue @Jatin described. I'm nodejs noob, but I have a feeling the original issue was with the closuring and object/function lifetime. My code is completely enclosed in one closure. In any case, why not chain on() instead of having it as a separate statement? – yuranos Nov 30 '20 at 22:50
7

It worked when I replaced req.pipe(str).pipe(res) with req.pipe(through(write, end)).pipe(res) which essentially makes sure that a new instance of through stream is created for every request.

Jatin
  • 14,112
  • 16
  • 49
  • 78