0

I have a node app that serves a react app as well as makes requests to Google Cloud Storage. The App works perfectly locally, but after I've deployed it to Heroku I get the following error whenever I make requests to any of my endpoints:

2017-05-26T21:53:34.426234+00:00 app[web.1]: app.post /upload_url Endpoint
2017-05-26T21:53:34.484393+00:00 app[web.1]: (node:34) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): RangeError: Invalid status code: 0

The first line is a console log to check if the endpoint is reached, the second line is the error. Here's the code for the /upload_url endpoint:

app.post('/upload_url', (req, res) => {
  console.log("app.post /upload_url Endpoint");
  var originalFileName = req.body["originalFileName"];
  var buf = crypto.randomBytes(16);
  var uniqueFilename = buf.toString('hex') + '_' + originalFileName;
  var file = bucket.file(uniqueFilename);

  file.createResumableUpload(function (err, uri) {
    if (!err) {
      var json = JSON.stringify({
        uri: uri,
        uniqueFilename: uniqueFilename,
        originalFileName: originalFileName
      }); 
      res.writeHead(200)
      res.end(json);
    } else {
      res.writeHead(err.code);
      res.end();
    }
  });
});

This endpoint is called by the react front end with the following fetch call:

function upload(file) {
  var data = new FormData();
  data.append('file', file);
  return fetch(`upload_url`,{
    method: 'POST',
    headers: new Headers({
      "Content-Type": "application/json",
    }),
    body: JSON.stringify({
        originalFileName: file.name
    })
   });
  }
}

Again, this works fine in development but not after deploying to Heroku. I've tried Heroku's suggestion of adding concurrency to the app (detailed here) without any luck. Any thoughts or suggestions on how to solve this problem would be very much appreciated.

EDIT:

bucket is a google cloud bucket and is defined like this:

const gcs = require('@google-cloud/storage')({
  projectId: 'my-project',
  keyFilename: process.env.GCS_KEYFILE
});
var bucket = gcs.bucket('my-bucket');

ANSWER:

While this didn't solve my issue entirely, by handling response error codes more appropriately I was able to determine that my actual problem is related to google cloud authentication. Here's my updated upload_url endpoint:

file.createResumableUpload(function (err, uri) {
  if (!err) {
    var json = JSON.stringify({
      uri: uri,
      uniqueFilename: uniqueFilename,
      originalFileName: originalFileName
    });
    res.writeHead(200)
    res.end(json);
  } else {
    if (err.code >= 100 && err.code < 600){
      console.error(err)
      res.writeHead(err.code);
      res.end();
    }else{
      console.error(err)
      res.writeHead(500);
      res.end();
    }
  }
 });
});
quicklikerabbit
  • 3,257
  • 6
  • 26
  • 39

1 Answers1

1

Refer to this answer https://stackoverflow.com/a/38258590/4348875, make sure err.code is a valid HTTP status code.

Yi Kai
  • 630
  • 6
  • 9
  • Thanks! Implementing this provided a more revealing error message, which in turn allowed me to discover that my problem is an authentication issue with google cloud. Question has been update to show how response codes are now handled. – quicklikerabbit May 28 '17 at 01:49