How to force parse request body as plain text instead of json in Express?
Asked Answered
H

8

52

I am using nodejs + Express (v3) like this:

app.use(express.bodyParser());
app.route('/some/route', function(req, res) {
  var text = req.body; // I expect text to be a string but it is a JSON
});

I checked the request headers and the content-type is missing. Even if "Content-Type" is "text/plain" it is parsing as JSON it seems.

Is there anyway to tell the middleware to always parse the body as a plain text string instead of as json? Earlier versions of req used to have req.rawBody that would get around this issue but now it does not anymore.

What is the easiest way to force parsing of the body as plain text/string in Express?

Herold answered 10/9, 2012 at 3:57 Comment(0)
H
29

If you remove the use of the bodyParser() middleware, it should be text. You can view the bodyParser docs for more info: http://www.senchalabs.org/connect/middleware-bodyParser.html

Remove this line:

app.use(express.bodyParser());

EDIT:

Looks like you're right. You can create your own rawBody middleware in the meantime. However, you still need to disable the bodyParser(). Note: req.body will still be undefined.

Here is a demo:

app.js

var express = require('express')
  , http = require('http')
  , path = require('path')
  , util = require('util');

var app = express();

function rawBody(req, res, next) {
  req.setEncoding('utf8');
  req.rawBody = '';
  req.on('data', function(chunk) {
    req.rawBody += chunk;
  });
  req.on('end', function(){
    next();
  });
}

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.use(rawBody);
  //app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
});

app.post('/test', function(req, res) {
  console.log(req.is('text/*'));
  console.log(req.is('json'));
  console.log('RB: ' + req.rawBody);
  console.log('B: ' + JSON.stringify(req.body));
  res.send('got it');
});

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

test.js

var request = require('request');

request({
  method: 'POST',
  uri: 'http://localhost:3000/test',
  body: {'msg': 'secret'},
  json: true
}, function (error, response, body) {
  console.log('code: '+ response.statusCode);
  console.log(body);
})

Hope this helps.

Hardhack answered 10/9, 2012 at 5:37 Comment(5)
Is I remove that line, req.body is undefined.Herold
That works - accepting your answer. Looks like since the formidable multi-part change they did not bother reimplementing rawBody in Express 3. I wonder if there is already a library that does those 7 lines of code for me...Herold
Any known methods to still have access to bodyParser and rawBody output?Cleromancy
This is GENIUS!!! your rawBody function worked where all others failed! Note to others: This makes the received string available on req.rawBody (NOT req.body). I tried body-parser and express.text() both with and without the NPM cors package, all of which failed to return a simple string.Merri
Nice solutions, but careful with that code when including this code as a middleware (tested express version 4.17.1), curl -X POST "myuri" -d "sdfsdf" => we never go in the on(data) or on(end) handler and it make the server hang (seems to be content-type relative).Bludgeon
C
53

By default bodyParser.text() handles only text/plain. Change the type options to include */json or */*.

app.use('/some/route', bodyParser.text({type: '*/*'}), function(req, res) {
  var text = req.body; // I expect text to be a string but it is a JSON
});

//or more generally:
app.use(bodyParser.text({type:"*/*"}));

You can find the docs here

Chessa answered 7/5, 2015 at 11:19 Comment(4)
was using application/text instead of text/plain. Thanks for pointing that out!Iwo
Is there a way so tell bodyParser not to generate an empty object body when there is no body in the request?Darees
Would parsing json with .text() even work? Isn't that what .json() is for?Cosgrove
This is the real answer to the questionArchetype
M
41

In express 4.x you can use the text parser from bodyParser https://www.npmjs.org/package/body-parser

just add in app.js

app.use(bodyParser.text());

Also in the desired route

router.all('/',function(req,res){
    console.log(req.body);

})
Malacostracan answered 27/11, 2014 at 18:14 Comment(0)
H
29

If you remove the use of the bodyParser() middleware, it should be text. You can view the bodyParser docs for more info: http://www.senchalabs.org/connect/middleware-bodyParser.html

Remove this line:

app.use(express.bodyParser());

EDIT:

Looks like you're right. You can create your own rawBody middleware in the meantime. However, you still need to disable the bodyParser(). Note: req.body will still be undefined.

Here is a demo:

app.js

var express = require('express')
  , http = require('http')
  , path = require('path')
  , util = require('util');

var app = express();

function rawBody(req, res, next) {
  req.setEncoding('utf8');
  req.rawBody = '';
  req.on('data', function(chunk) {
    req.rawBody += chunk;
  });
  req.on('end', function(){
    next();
  });
}

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.use(rawBody);
  //app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
});

app.post('/test', function(req, res) {
  console.log(req.is('text/*'));
  console.log(req.is('json'));
  console.log('RB: ' + req.rawBody);
  console.log('B: ' + JSON.stringify(req.body));
  res.send('got it');
});

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

test.js

var request = require('request');

request({
  method: 'POST',
  uri: 'http://localhost:3000/test',
  body: {'msg': 'secret'},
  json: true
}, function (error, response, body) {
  console.log('code: '+ response.statusCode);
  console.log(body);
})

Hope this helps.

Hardhack answered 10/9, 2012 at 5:37 Comment(5)
Is I remove that line, req.body is undefined.Herold
That works - accepting your answer. Looks like since the formidable multi-part change they did not bother reimplementing rawBody in Express 3. I wonder if there is already a library that does those 7 lines of code for me...Herold
Any known methods to still have access to bodyParser and rawBody output?Cleromancy
This is GENIUS!!! your rawBody function worked where all others failed! Note to others: This makes the received string available on req.rawBody (NOT req.body). I tried body-parser and express.text() both with and without the NPM cors package, all of which failed to return a simple string.Merri
Nice solutions, but careful with that code when including this code as a middleware (tested express version 4.17.1), curl -X POST "myuri" -d "sdfsdf" => we never go in the on(data) or on(end) handler and it make the server hang (seems to be content-type relative).Bludgeon
A
25

Express understands by content-type how to decode a body. It must have specific decoders in middlewares, which is embedded into the library from 4.x:

app.use(express.text())
app.use(express.json())
Asis answered 24/8, 2019 at 20:26 Comment(1)
👍, but I'm pretty sure these middle-wares were only added to the package in v4.16.0 and later versions: github.com/expressjs/express/releases/tag/4.16.0Rush
P
4

Two important things to achieve this.

  1. You need to add the text middleware in order to process text in the body
  2. You need to set the content type by adding the right header "Content-type: text/plain" in the request

Here is the sample code for both.

const express = require('express');
const app = express();
const bodyParser = require('body-parser')
//This is the needed text parser middleware 
app.use(bodyParser.text()); 

app.post('/api/health/', (req, res) => {
    res.send(req.body);
});

const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on ${port} ${new Date(Date.now())}`));

Save this as index.js.

Install dependencies.

npm i -S express 
npm i -S body-parser

Run it.

node index.js

Now send a request to it.

curl -s -XPOST -H "Content-type: text/plain" -d 'Any text or  json or whatever {"key":value}' 'localhost:3000/api/health'

You should be able to see it sending back whatever you posted.

Pirouette answered 26/3, 2020 at 12:55 Comment(0)
G
3

You can use the plainTextParser (https://www.npmjs.com/package/plaintextparser) middleware..

let plainTextParser = require('plainTextParser');
app.use(plainTextParser());

or

app.post(YOUR_ROUTE, plainTextParser, function(req, res) {             
  let text = req.text;

  //DO SOMETHING....
}); 
Goon answered 1/9, 2016 at 17:5 Comment(0)
B
2

I did it:

router.route('/')
.post(function(req,res){
    var chunk = '';

    req.on('data', function(data){
        chunk += data; // here you get your raw data.
    })        

    req.on('end', function(){

        console.log(chunk); //just show in console
    })
    res.send(null);

})
Bytom answered 21/7, 2017 at 16:41 Comment(0)
J
1

Make sure the version of express and bodyParser has been upgraded to the appropriate versions. Express ˜4.x and bodyParser ˜1.18.x. That should do it. With that in place the following should work

app.use(bodyParser.text());

Joel answered 23/1, 2018 at 1:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.