firebasegoogle-cloud-functionsfirebase-clihttp-toolkit

rawBody is missing in firebase cloud functions emulator


https://firebase.google.com/docs/functions/http-events indicates that a rawBody parameter should exist on req. However, it is undefined in my local emulator.

What am I doing wrong?

$ firebase --version
7.8.1

My client-side javascript code for POSTing the binary data:

var buffer = new ArrayBuffer(4);
var view = new DataView(buffer);

function writeUTFBytes(view, offset, string) {
    var lng = string.length;
    for (var i = 0; i < lng; i++) {
        view.setUint8(offset + i, string.charCodeAt(i));
    }
}

writeUTFBytes(view, 0, 'RIFF');

var blob = new Blob([view]);

fetch('http://localhost:5001/firebase-project-name/us-central1/endpointName', {
  method: 'POST',
  body: blob
})

My index.js firebase cloud functions code:

const functions = require('firebase-functions');

exports.endpointName = functions.https.onRequest((req, res) => {
  res.set('Access-Control-Allow-Origin', 'http://localhost:3000');

  console.log(req.rawBody);
  console.log(typeof req.rawBody);

  res.end();
});

When I run the function, here's what I get:

$ firebase emulators:start --only functions
<snip>
i  functions: Beginning execution of "endpointName"
>  
>  undefined

I've confirmed with HTTP Toolkit that the body is in fact sent from my browser:

HTTP Toolkit showing 'RIFF' as body


Solution

  • I figured out that if I set a content-type to application/octet-stream or audio/wave then rawBody suddenly appears!

      fetch(url, {
        method: 'POST',
        headers: new Headers({
          'Content-Type': 'audio/wav',
        }),
        body: blob
      })
    

    However! I had to modify my function to get the OPTIONS HTTP request to succeed for my browser to ask whether it was ok to include the Content-Type header, otherwise, the actual request was never sent:

      res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
    
      if (req.method === 'OPTIONS') {
          // Send response to OPTIONS requests
          res.set('Access-Control-Allow-Methods', 'OPTIONS, POST');
          res.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length');
          res.set('Access-Control-Max-Age', '3600');
          return res.status(204).send('');
      }
    

    However, I'm still curious why no rawBody happens without a content-type header. At the very least, there could be some docs that walk through an end to end example of sending binary data and using rawBody.