azure-function-express
azure-function-express copied to clipboard
Content-Type doesn't work correctly
I'm trying to make POST request and send JSON data to Azure Function using application/json Content-Type. But the function call hangs and return timeout instead of result.
App has the following configuration
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Locally such expressjs application works perfectly. But looks like some trouble with Content-Type on Azure.
However when I change configuration to this one
app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
My POST requests pass. But for x-www-form-urlencoded it still can't parse the data and returns timeout.
Could you please help me to understand why it doesn't work? Thank you
app.use((req, res, next) => {
req.get('Content-Type'); // it returns application/json
});
But this one doesn't work
app.use(bodyParser.json());
---- OR ----
app.use(bodyParser.json({ type: 'application/json' }));
So, comparing local execution with azure, I can say that req object is stream object locally, and it should be a stream on azure, but it doesn't. And that's why bodyParser can't read stream and parse incoming data...
When I started with this library my first test is doing a post. I couldn't figure out why it was hanging. A search found your issue and I was saved by using application/*+json. I dont really know why that works but it works so thanks!
Now I am testing file upload which was using bodyparser with type application/octet-stream and multer it is not working either. Not sure if this is related to content type again or something else. Did you ever find a solution?
application/*+json is not actually the way. I did some trick to manage bodyParser stuff.
if (process.env.CLOUD === 'azure') { // For azure cloud apply specific body parser
app.use(azureBodyParser());
} else {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
}
So here I check first the environment. If it's not azure then just follow usual express bodyParser style. For azure environment I created custom middleware to handle request object.
'use strict';
const queryString = require('query-string');
/**
* Azure body parser
*/
function azureBodyParser() {
return function(req, res, next) {
// x-www-form-urlencoded
if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
req.body = queryString.parse(req.body, { arrayFormat: 'bracket' });
}
next();
};
}
module.exports = azureBodyParser;
This can be different. You can add more checks if you want.
So basically for application/json content-type azure itself fulfill req.body object with proper request data as json object.
For application/x-www-form-urlencoded content-type data comes in raw format, so I used query-string library to parse incoming data and fulfill req.body with json object.
For your case with multer I didn't try anything actually. I assume data will come as buffer object, and you should add one more check for content-type application/octet-stream and parse it by yourself, maybe using some existing libraries. But I'm not sure, you better try yourself, I may be wrong.
I opened a PR which changes the IncomingMessage (wrapped req object) to be a Readable stream with the rawBody pushed. This seems to fix this issue
Thanks @dcollien . Hope it will.
Here is some useful information about this ticket I've found so far https://stackoverflow.com/questions/50043746/azure-function-doesnt-respond-if-content-type-application-json
@iredjee I think it might not so much to do with the content-type, but the same cause as #22 - if the request object isn't a stream, then it can't pipe the original request body into a stream-consuming JSON parser. The original code just did a NOOP if it tried to be used as a stream - hence why it might have just timed out. Changing the request object to extend a stream (as it is in express) might be the fix (I hope).
edit: if you'd like to try it out, you can change your package.json to use:
"dependencies": {
"azure-function-express": "github:dcollien/azure-function-express#dist"
}