I've been trying to handle POSTs (multipart/form-data) with a Firebase function and Express but it just doesn't work. Tried this in local server and it works just fine. Everything's the same except it's not contained in a Firebase function.
Besides screwing up the request object it seems it also screws up the way busboy works.
I've tried different solutions presented here but they just don't work. As one user mentions, the callbacks passed to busboy (to be called when a 'field' is found or when it finishes going through the data) are never called and the function just hangs.
Any ideas?
Here's my function's code for reference:
const functions = require('firebase-functions');
const express = require('express');
const getRawBody = require('raw-body');
const contentType = require('content-type')
const Busboy = require('busboy');
const app = express();
const logging = (req, res, next) => {
console.log(`> request body: ${req.body}`);
next();
}
const toRawBody = (req, res, next) => {
const options = {
length: req.headers['content-length'],
limit: '1mb',
encoding: contentType.parse(req).parameters.charset
};
getRawBody(req, options)
.then(rawBody => {
req.rawBody = rawBody
next();
})
.catch(error => {
return next(error);
});
};
const handlePostWithBusboy = (req, res) => {
const busboy = new Busboy({ headers: req.headers });
const formData = {};
busboy.on('field', (fieldname, value) => {
formData[fieldname] = value;
});
busboy.on('finish', () => {
console.log(`> form data: ${JSON.stringify(formData)}`);
res.status(200).send(formData);
});
busboy.end(req.rawBody);
}
app.post('/', logging, toRawBody, handlePostWithBusboy);
const exchange = functions.https.onRequest((req, res) => {
if (!req.path) {
req.url = `/${req.url}`
}
return app(req, res)
})
module.exports = {
exchange
}
Please read the documentation for handling multipart form uploads.
... if you want your Cloud Function to process multipart/form-data, you can use the rawBody property of the request.
Because of the way Cloud Functions pre-processes some requests, you can expect that some Express middleware will not work, and that's what you're running into.
The documentation Doug referred to in his answer is good. An important caveat though is that rawBody
does not work in the emulator. The workaround is to do:
if (req.rawBody) {
busboy.end(req.rawBody);
}
else {
req.pipe(busboy);
}
As described in this issue: https://github.com/GoogleCloudPlatform/cloud-functions-emulator/issues/161#issuecomment-376563784
来源:https://stackoverflow.com/questions/48289824/handling-multipart-form-data-post-with-express-in-cloud-functions