31


I am trying to make a request to my node JS server which accepts post/put call. The parameters I am trying to send with post call via chai is not visible on server (req.body.myparam).
I have tried with below post request but ended with not results:-

var host = "http://localhost:3000";
var path = "/myPath";
 chai.request(host).post(path).field('myparam' , 'test').end(function(error, response, body) {

and

chai.request(host).post(path).send({'myparam' : 'test'}).end(function(error, response, body) {

Node JS code is given below:-

app.put ('/mypath', function(req, res){                     //Handling post request to create league
    createDoc (req, res);
})


app.post ('/mypath', function(req, res){                        //Handling post request to create league
    createDoc (req, res);
})

var createDoc = function (req, res) {
    var myparam = req.body.myparam;                                 //league id to create new league
    if (!myparam) {
        res.status(400).json({error : 'myparam is missing'});
        return;
    }       
};

Above code goes to myparam is missing.

Please let me know what is the best way to do the same.
Thanks in Advance.

SCJP1.6 PWR
  • 371
  • 1
  • 4
  • 7

2 Answers2

39

The way you have written, I assume that you used chai-http package. The .field() function does not work in chai-http. Another user pointed it out here and opened an issue on github.

Here is how you could have written:

.set('content-type', 'application/x-www-form-urlencoded')
.send({myparam: 'test'})

Here is the full code that successfully passes parameters to the server:

test.js

'use strict';
var chai = require('chai');
var chaiHttp = require('chai-http');

chai.use(chaiHttp);

describe('Test group', function() {
    var host = "http://" + process.env.IP + ':' + process.env.PORT;
    var path = "/myPath";

    it('should send parameters to : /path POST', function(done) {
        chai
            .request(host)
            .post(path)
            // .field('myparam' , 'test')
            .set('content-type', 'application/x-www-form-urlencoded')
            .send({myparam: 'test'})
            .end(function(error, response, body) {
                if (error) {
                    done(error);
                } else {
                    done();
                }
            });
    });
});

server.js

'use strict';
var bodyParser  = require("body-parser"),
    express     = require("express"),
    app         = express();

app.use(bodyParser.urlencoded({extended: true}));

app.put ('/mypath', function(req, res){  //Handling post request to create league
    createDoc (req, res);
});

app.post ('/mypath', function(req, res){  //Handling post request to create league
    createDoc (req, res);
});

var createDoc = function (req, res) {
    console.log(req.body);
    var myparam = req.body.myparam; //league id to create new league
    if (!myparam) {
        res.status(400).json({error : 'myparam is missing'});
        return;
    }
};

app.listen(process.env.PORT, process.env.IP, function(){
    console.log("SERVER IS RUNNING");
});

module.exports = app;
Louis
  • 146,715
  • 28
  • 274
  • 320
C00bra
  • 401
  • 4
  • 5
  • This worked for me. It's funny because the docs say to use the .field() method when posting form data, but maybe that doesn't work if you're using the bodyParser in this way on the server? – Gabriel Kunkel Nov 02 '16 at 20:53
  • how to attach a file in this? I know this is the code .attach('imageField', fs.readFileSync('avatar.png'), 'avatar.png') But am not sure where to attach it – Kannan T Feb 21 '18 at 10:20
  • What do you `module.exports = app;` for if you don't require it in your tests? If you export it you can require it and then `chai.request(server).post(path)`. This will let you `mock` or `spy`, e.g. using https://www.npmjs.com/package/sinon-chai – Alexander Jul 31 '18 at 19:31
  • 8 hours of research AND FINALLY THIS `.set('content-type', 'application/x-www-form-urlencoded')` SOLVED EVERYTHING!!! Thank you a million times @C00bra. This should be the marked answer! – Tenzolinho Jun 06 '19 at 13:18
13

I found two ways to solve the issue with empty req.body.

  1. body as a form data

    .put('/path/endpoint')
    .type('form')
    .send({foo: 'bar'})
    // .field('foo' , 'bar')
    .end(function(err, res) {}
    
    // headers received, set by the plugin apparently
    'accept-encoding': 'gzip, deflate',
    'user-agent': 'node-superagent/2.3.0',
    'content-type': 'application/x-www-form-urlencoded',
    'content-length': '127',
    
  2. body as application/json

    .put('/path/endpoint')
    .set('content-type', 'application/json')
    .send({foo: 'bar'})
    // .field('foo' , 'bar')
    .end(function(err, res) {}
    
    // headers received, set by the plugin apparently
    'accept-encoding': 'gzip, deflate',
    'user-agent': 'node-superagent/2.3.0',
    'content-type': 'application/json',
    'content-length': '105',
    

In both cases I use .send({foo: 'bar'}) and not .field('foo' , 'bar').

The issue apparently has nothing to do with chai-http. It is superagent's issue. And chai-http is using superagent under the hood.

superagent tries to play Machine Learning and make guesses for us. Here is what their docs say:

By default sending strings will set the Content-Type to application/x-www-form-urlencoded

SuperAgent formats are extensible, however by default "json" and "form" are supported. To send the data as application/x-www-form-urlencoded simply invoke .type() with "form", where the default is "json".

  request.post('/user')
    .type('form')
    .send({ name: 'tj' })
    .send({ pet: 'tobi' })
    .end(callback)

chai-http biggest fault is that they didn't document their plugin properly. You have to search for answers all over the Internet and not on chai-http GitHub page where it must be.

Green
  • 28,742
  • 61
  • 158
  • 247
  • how to attach a file in this? I know this is the code .attach('imageField', fs.readFileSync('avatar.png'), 'avatar.png') But am not sure where to attach it – Kannan T Feb 21 '18 at 10:20