Proper way to return stream from Firebase callable function (Cloud function)?

Viewed 37

What's the proper way to return stream from Firebase callable function? I want it to behave like a proxy and return the response stream directly. Currently, I wait for response and append them like shown below. I don't think it's the right way to do it as it won't return stream directly.

const axios = require('axios');
const functions = require("firebase-functions");
const {PassThrough} = require("stream");
exports.create = functions.https.onCall(async(data, context) => {

    const options = {
        method: 'POST',
        url: '...someurl',
       ,
        responseType: 'stream'
      };

    const response =  await axios(options)

    const chunks = response.data.pipe(new PassThrough({encoding:'base64'}));

    // then we use an async generator to read the chunks
    let str = '';
    for await (let chunk of chunks) {
        str += chunk;
    }
    return str;
}
1 Answers

If you have access to cloud storage buckets you can upload the data to a bucket, generate a download URL and redirect your HTTP request to the download link

//using admin sdk and express
import * as admin from "firebase-admin";
const bucket = admin.storage().bucket('<bucket name>');
await bucket.file('<filename>').save(data).catch();

bucket.file('<filename>').getSignedURL({
   action: 'read',
   expires: Date.now() + 600000, //expires in 10 minutes
}).then(url => {
   response.redirect(url[0]); //redirect to download URL
}).catch(error => {
   console.log(error);
})

You will have to change your storage permissions settings to authenticate the download URL creation and access. You can do this in the rules section of the storage project category on firebase

service firebase.storage {
  match /b/{bucket}/o {
    match /<bucket name>/{allPaths=**} {
      allow read: if true;
      allow write: if request.auth != null; //all other locations are secured by auth
    }
    match /{allPaths=**} {
      allow read, write: if request.auth != null; 
    }
  }
}

Ensure you replace <bucket name> with the name of your bucket. This rule allows anyone to read from the databucket but not write to it unless authorized. All other locations are secure. If you are storing confidential information do not use this permissions workaround and secure the download URL creation by correct auth.

Related