Trying to build a REST API can be really frustrating. You install Express.js with mongoose or mongodb, and then create a schema, just following the instructions, and you think everything should work. You set up Postman to test the API, hit the API, and Postman stays at “sending request..” for a while. You wait… and wait… and then eventually you see the message “Could not get any response”.
Sometimes, it works fine to set everything up all at once. But, it can often happen that there are just too many moving parts. When that happens, and something breaks, it can be very difficult to figure out the point of failure.
As an example, suppose you have an Express router
which handles a POST
request like this using a mongoose model:
const router = require('express').Router();
// ... mongoose code here
router.post('/registerKitten', async (req, res) => {
const fluffy = new Kitten({ name: 'fluffy' });
try {
await fluffy.save();
res.json(fluffy);
} catch(err) {
res.status(400).send(err);
}
})
If Postman times out when hitting the API, you can’t know whether the problem is in Express.js or Mongoose.
The first, simple thing you can do is add some console logging to see if your route is executed:
const router = require('express').Router();
// ... mongoose code here
router.post('/registerKitten', async (req, res) => {
console.log("registerKitten");
const fluffy = new Kitten({ name: 'fluffy' });
try {
console.log("awaiting save...");
await fluffy.save();
console.log("save is finished");
res.json(fluffy);
} catch(err) {
res.status(400).send(err);
}
})
That won’t tell you the whole story, however. If you see “awaiting save…” but don’t see “save is finished”, then doing this has helped you locate the problem – mongoose is hanging.
At this point, you may be better off writing a small Node.js test script which will just exercise the code related to mongoose, independently of Express. That way, you can debug the problem without having to deal with Express code or restart your Express server.
Here’s some sample code. You’ll have to adjust this to your own specific case, but the idea is to put this code into a script (test.js
) and run it from the command line with node test.js
:
"use strict";
const mongoose = require('mongoose');
const Kitten = require('./models/Kitten');
mongoose.connect(process.env.MONGO_DB_URL, { useNewUrlParser: true });
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
// Set up some mock user data
const fluffy = new Kitten({ name: 'fluffy' });
// When the db is open, 'save' this data.
db.once('open', async function () {
// we're connected!
console.log("db opened... going to save the kitten");
await fluffy.save();
console.log("printing fluffy");
console.log(fluffy);
db.close();
});
// Print that db connection has been closed.
db.once('close', function () {
console.log('close');
});
Notice that the code references an environment variable, process.env.MONGO_DB_URL
. You’ll need to set that in your terminal. In Linux, you can do that by using the export
command: export MONGO_DB_URL=mongodb://127.0.0.1:27017/myappdb
.