Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse HTTP request with a missing content type in Express/ NodeJs, by assuming a default content type?

How can I get access to the POST data in a request, if the express bodyParser does not fire?

var server = express();
server.use(express.bodyParser());
server.post('/api/v1', function(req, resp) {
  var body = req.body;
  //if request header does not contain 'Content-Type: application/json'
  //express bodyParser does not parse the body body is undefined
  var out = {
    'echo': body
  };
  resp.contentType('application/json');
  resp.send(200, JSON.stringify(out));
});

Note: in ExpressJs 3.x+ req.body is not automatically available, and requires bodyParser to activate.

If a content type header is not set, is it possible to specify a default content type of application/json and trigger the bodyParser?

Otherwise is it possible to access the POST data using the bare nodejs way from within this express POST function?

(e.g. req.on('data', function...)

like image 663
bguiz Avatar asked Jun 21 '13 04:06

bguiz


2 Answers

You have a bunch of options including manually invoking the express (connect, really) middleware functions yourself (really, go read the source code. They are just functions and there is no deep magic to confuse you). So:

function defaultContentTypeMiddleware (req, res, next) {
  req.headers['content-type'] = req.headers['content-type'] || 'application/json';
  next();
}

app.use(defaultContentTypeMiddleware);
app.use(express.bodyParser());
like image 113
Peter Lyons Avatar answered Oct 26 '22 00:10

Peter Lyons


I use this middleware, before bodyParser kicks in, which may help. It peeks at the first byte of the request stream, and makes a guess. This particular app only really handles XML or JSON text streams.

app.use((req,res, next)=>{
    if (!/^POST|PUT$/.test(req.method) || req.headers['content-type']){
        return next();
    }
    if ((!req.headers['content-length'] || req.headers['content-length'] === '0') 
            && !req.headers['transfer-encoding']){
        return next();
    }
    req.on('readable', ()=>{
        //pull one byte off the request stream
        var ck = req.read(1);
        var s = ck.toString('ascii');
        //check it
        if (s === '{' || s==='['){req.headers['content-type'] = 'application/json';}
        if (s === '<'){req.headers['content-type'] = 'application/xml'; }
        //put it back at the start of the request stream for subsequent parse
        req.unshift(ck);
        next();
    });
});
like image 29
san1t1 Avatar answered Oct 26 '22 00:10

san1t1