Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content-Type doesn't work correctly #15

Open
ghost opened this issue Apr 27, 2018 · 7 comments
Open

Content-Type doesn't work correctly #15

ghost opened this issue Apr 27, 2018 · 7 comments

Comments

@ghost
Copy link

ghost commented Apr 27, 2018

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

@ghost
Copy link
Author

ghost commented Apr 27, 2018

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' }));

@ghost
Copy link
Author

ghost commented Apr 27, 2018

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...

@spacem
Copy link

spacem commented Jun 21, 2018

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?

@ghost
Copy link
Author

ghost commented Jun 21, 2018

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.

@dcollien
Copy link

dcollien commented Mar 6, 2019

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

@ghost
Copy link
Author

ghost commented Mar 6, 2019

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

@dcollien
Copy link

dcollien commented Mar 7, 2019

@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"
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants