0
votes

I´d like to save a selected image from unsplash in a cloud function - to run it in background. Here´s my code:

export const getUnsplashCron = functions
  .region('europe-west1')
  .runWith({ memory: '512MB', timeoutSeconds: 15 })
  .https.onRequest(async(req, res) => {

    if (!req.query.url) {
      res.status(300).send('no url');
    }

    return request({
      url: req.query.url + '?client_id=' + environment.unsplash.appId,
      encoding: null
    }, (err, response, body) => {
      if (!err && response.statusCode === 200) {

        const stream = require('stream');
        const bufferStream = new stream.PassThrough();

        bufferStream.end(Buffer.from(body, 'base64'));

        const file = admin.storage().bucket().file('name.jpg');

        bufferStream.pipe(
          file.createWriteStream({
            public: true
          }))
          .on('error', function(error) {
            console.log(error);
            return res.status(500).send(error)
          })
          .on('finish', function() {

            const config: GetSignedUrlConfig = {
              action: 'read',
              expires: '01-01-2025'
            };
            file.getSignedUrl(config, function(error, url) {
              console.log(url);
              if (error) {
                return res.status(500).send(error);
              }
              return res.status(500).send(url);
            });

          });


      }
    });

  });

But I´m getting an

Error: Not Found at Util.parseHttpRespBody (/srv/node_modules/@google-cloud/common/build /src/util.js:172:38) at Util.handleResp (/srv/node_modules/@google-cloud/common/build/src/util.js:116:117) at retryRequest (/srv/node_modules/@google-cloud/common/build/src/util.js:404:22) at onResponse (/srv/node_modules/retry-request/index.js:200:7) at /srv/node_modules/teeny-request/build/src/index.js:158:17 at at process._tickDomainCallback (internal/process/next_tick.js:229:7) code: 404, errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ], response: undefined, message: 'Not Found' }

What am I doing wrong?!

1

1 Answers

0
votes

You should use promises to handle asynchronous tasks (like the HTTP call to unsplash, or the write to Cloud Storage). By default request does not return promises, so you need to use an interface wrapper for request, like request-promise.

You should therefore modify your code as follows:

const rp = require('request-promise');
.....

export const getUnsplashCron = functions
  .region('europe-west1')
  .runWith({ memory: '512MB', timeoutSeconds: 15 })
  .https.onRequest(async(req, res) => {

  .......

  const options = {
    uri: req.query.url + '?client_id=' + environment.unsplash.appId
  };

  rp(options)
    .then(response => {
      .... //Upload your file
      res.send('Success');
    })
    .catch(err => {
      // API call failed...
      res.status(500).send('Error': err);
    });
};

You may watch this official video series for more detail: https://firebase.google.com/docs/functions/video-series/ (in particular the 3 videos titled "Learn JavaScript Promises").