3

I'm trying to "proxy" some file with an express app. Why the code below doesn't work?

var app = require('express')()
var request = require('superagent')
app.get('/image', function(req, res, next) {
  request('http://s3.amazonaws.com/thumbnails.illustrationsource.com/huge.104.520060.JPG')
    .then(function(_res) {
      _res.pipe(res)
    })
})

app.listen(3001, function() {
  console.log('listen')
})

When I "wget" a file directly it works:

$ wget http://s3.amazonaws.com/thumbnails.illustrationsource.com/huge.104.520060.JPG
--2016-07-20 11:44:33--  http://s3.amazonaws.com/thumbnails.illustrationsource.com/huge.104.520060.JPG
Resolving s3.amazonaws.com... 54.231.120.106
Connecting to s3.amazonaws.com|54.231.120.106|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21026 (21K) [image/jpeg]
Saving to: 'huge.104.520060.JPG'

huge.104.520060.JPG                           100%[==============================================================================================>]  20.53K  --.-KB/s    in 0.1s

2016-07-20 11:44:34 (203 KB/s) - 'huge.104.520060.JPG' saved [21026/21026]

when I call my enpdpoint it never finishes:

$ wget localhost:3001/image
--2016-07-20 11:45:00--  http://localhost:3001/image
Resolving localhost... 127.0.0.1, ::1
Connecting to localhost|127.0.0.1|:3001... connected.
HTTP request sent, awaiting response...

Some details:

$ npm -v
3.9.5

$ npm list --depth=0
express-superagent-pipe-file
├── express@4.14.0
└── superagent@2.1.0
kharandziuk
  • 12,020
  • 17
  • 63
  • 121

2 Answers2

3

A superagent's response object should not be treated as a stream, because it may already be the result of automatic serialization (e.g. from JSON to a JavaScript object). Rather than using the response object, the documentation on piping data states that you can directly pipe the superagent request to a stream:

var app = require('express')()
var request = require('superagent')
app.get('/image', function(req, res, next) {
  request('http://s3.amazonaws.com/thumbnails.illustrationsource.com/huge.104.520060.JPG')
    .pipe(res)
})

app.listen(3001, function() {
  console.log('listen')
})
E_net4
  • 27,810
  • 13
  • 101
  • 139
  • Thanks! It works. But what does `_res.pipe` function do in the case? – kharandziuk Jul 20 '16 at 10:47
  • 1
    @kharandziuk It appears to be implementation-dependent. A `Response` object is indeed a `ReadableStream` in Node.js, according to [the source code](https://github.com/visionmedia/superagent/blob/v2.1.0/lib/node/response.js#L26-L27), but it's a private API that should not be used externally. Nothing in the documentation shows that a response object can be used as a readable stream anyway. – E_net4 Jul 20 '16 at 10:55
  • 1
    In case you're still wondering what happens after `_res.pipe`, here's a good comment: https://github.com/visionmedia/superagent/issues/684#issuecomment-233959045 – E_net4 Jul 20 '16 at 14:06
-1

With Promises, download the following way:

const fs = require('fs');
const path = require('path');

const download = (url) => {
    return superagent.get(url)
    .then((response) => {
        const stream = fs.createWriteStream('file.ext');
        return response.pipe(stream);
    });
};
treecoder
  • 43,129
  • 22
  • 67
  • 91