Search code examples
jsonrestify

Restify HTTP Post Invalid JSON


I'm trying to send Post data using Restify and Postman to send the request.

But no matter what data I send via Post, I get the following error:

{ InvalidContentError: Invalid JSON: Unexpected token o in JSON at position 1
    at Server.parseJson (/_code/aService/node_modules/restify/lib/plugins/jsonBodyParser.js:40:25)
    at next (/_code/aService/node_modules/restify/lib/server.js:1028:30)
    at f (/_code/aService/node_modules/once/once.js:25:25)
    at Server.readBody (/_code/aService/node_modules/restify/lib/plugins/bodyReader.js:73:13)
    at next (/_code/aService/node_modules/restify/lib/server.js:1028:30)
    at f (/_code/aService/node_modules/once/once.js:25:25)
    at parseJson (/_code/aService/node_modules/restify/lib/plugins/jsonBodyParser.js:74:16)
    at Server.parseBody (/_code/aService/node_modules/restify/lib/plugins/bodyParser.js:96:13)
    at next (/_code/aService/node_modules/restify/lib/server.js:1028:30)
    at f (/_code/aService/node_modules/once/once.js:25:25)
  jse_shortmsg: 'Invalid JSON: Unexpected token o in JSON at position 1',
  jse_info: {},
  message: 'Invalid JSON: Unexpected token o in JSON at position 1',
  body: 
   { code: 'InvalidContent',
     message: 'Invalid JSON: Unexpected token o in JSON at position 1' },
  context: null }

Here is my cleaned up code... API.js

const baseRouter    = require('./routes/BaseRoutes');
const restify       = require('restify'),
    restifyPlugin   = require('restify').plugins,
    chalk           = require('chalk'),
    util            = require('util'),
    compression     = require('compression');
const env = process.env.ENVIRONMENT || 'development';
const server = restify.createServer({
    name: "Test API",
    version: "1.0.0",
    url: "localhost"
});
server.pre(restify.pre.sanitizePath()); // sanitizePath: cleans up duplicate or trailing / on the URL
server.pre(function (req, res, next) {
    logger.silly(chalk.yellow.bold(`Request:\n${req}`));
    return next();
});

// The "use" handler chains is executed after a route has been chosen to service the request
server.use(compression()); // compress all responses
server.use(restifyPlugin.acceptParser(server.acceptable)); // Accept header
server.use(restifyPlugin.authorizationParser()); // Authorization header
server.use(restifyPlugin.dateParser()); // expires requests based on current time + delta
server.use(restifyPlugin.queryParser({ mapParams: true })); // Parses URL query paramters into req.query
server.use(restifyPlugin.jsonp()); // parses JSONP callback
server.use(restifyPlugin.gzipResponse()); // gzips the response if client accepts it
server.use(restifyPlugin.bodyParser()); // parses POST bodies to req.body
server.use(restifyPlugin.jsonBodyParser({ mapParams: true })); // parses JSON POST bodies to req.body
server.use(restifyPlugin.acceptParser(server.acceptable));
server.use(restifyPlugin.fullResponse()); //

server.use(restifyPlugin.throttle({
    burst: 100, // the amount of requests to burst to
    rate: 50, // number of requests/second to allow
    username: true,
    overrides: {
        '192.168.1.1': {
            rate: 0,        // unlimited
            burst: 0
        }
    }
}));
// When a client request is sent for a route that exist, but has a content-type mismatch, restify will emit this event. Note that restify checks for listeners on this event, and if there are none, responds with a default 415 handler. It is expected that if you listen for this event, you respond to the client.
server.on('InvalidContent', function (req, res, err, cb) {
    console.log("line 122");
    logger.error(chalk.red.bold(util.inspect(err)));
    res.send();
});
// Emitted after a route has finished all the handlers you registered. You can use this to write audit logs, etc. The route parameter will be the Route object that ran.
server.on('after', function (req, res, route) {
    logger.verbose(chalk.green.bold(`Route:\n ${util.inspect(route)}`));
    logger.silly(chalk.green.bold(`Response:\n ${util.inspect(res)}`));
    logger.verbose(chalk.green.bold(`${res}`));
    logger.info(chalk.magenta.bold(`Request began at ${req.time()}ms`));
    logger.verbose(chalk.green.bold(`status code: ${res.statusCode}`));
    logger.verbose(chalk.green.bold(`data: ${res._data}`));
});

// *** apply routes...
baseRouter.applyRoutes(server, process.env.ROUTE_PREFIX);

// Lift Server -- the server is up...the force is alive!
server.listen(process.env._PORT, function () {
    logger.info(chalk.cyan.bold(`>>> >>>>> >>>>>>> ${server.name} is up!`));
    elapsedTime("");

    logger.verbose();
    logger.info(chalk.yellow(`Server listening on port: ${String(process.env._PORT)}`));
    logger.info(chalk.yellow(`Current Log Level set to: ${String(logger.transports.console.level)}`));

    logger.verbose(chalk.green.bold(`memory usage: ${Math.round((process.memoryUsage().heapUsed / 1024 / 1024) * 100) / 100} MB`));
    logger.verbose(chalk.green.bold(`uptime: ${util.inspect(process.uptime())}`));
    logger.verbose(chalk.green.bold(`pid: ${util.inspect(process.pid)}`));

    logger.verbose(chalk.magenta.bold('loaded modules...'));
    logger.verbose(
        Object.keys(require('../package.json').dependencies).forEach(function (key) {
            let _obj = require('../package.json').dependencies[key];
            logger.verbose(chalk.magenta(`${key} : ${_obj}`));
        })
    );


});

BaseRoutes.js

const chalk     = require('chalk'),
    util        = require('util'),
    _Router     = require('restify-router').Router,
    router      = new _Router(),
    errors      = require('restify-errors');

function hello(req, res, next) {
    if (!req.is('application/json')) {
        return next(new errors.InvalidContentError("Expects 'application/json'"));
    }

    logger.info(chalk.yellow.bold(`Requested route: /api/v1/hello`));
    res.send('ok');
    next();
}

router.post({path: '/hello', version: '1.0.0'}, hello);

module.exports = router;

This is the JSON that I am Posting

{
    "name": "John Smith"
}

As you can see -- I am not doing anything out of the ordinary...but yet I am running into the error of "'Invalid JSON: Unexpected token o in JSON at position 1'"

What am I missing?


Solution

  • You cannot use both bodyParser and jsonBodyParser middlewares - you have to choose one or the other, it seems.

    I ran into the same exact error message, and when I removed the bodyParser middleware and only used the jsonBodyParser, the error went away - my guess is that bodyParser is doing something to manipulate the request body so when the jsonBodyParser gets it, it's no longer well-formed JSON, and fails to parse correctly.