I'm building a pretty simple API to do a basic CRUD operations on a local mongo database. The code looks fine for me but somehow the CRUD operations results on a pending request which never ends.
Here the parts of the code:
spawn.model.js (Model corresponding to database collection)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SpawnSchema = Schema({
Name: {
type: String,
unique: false,
required: true
}
}, { timestamps: true });
module.exports = mongoose.model('spawns', SpawnSchema);
spawn.controller.js
var Spawn = require('../models/Spawn/spawn.model');
exports.getSpawns = function(req, res){
Spawn.find({}, function(spawns){
res.send(spawns);
});
}
Here the spawn.routes.js file:
var Spawns = require('../controllers/spawn.controller');
module.exports = function(app){
app.get('/list', Spawns.getSpawns);
}
And then finally the server.js file:
var express = require('express');
var bodyParser = require('body-parser');
var properties = require('./config/properties');
var db = require('./config/database');
var app = express();
//configure bodyparser
var bodyParserJSON = bodyParser.json();
var bodyParserURLEncoded = bodyParser.urlencoded({ extended: true });
// call the database connectivity function
db();
// configure app.use()
app.use(bodyParserJSON);
app.use(bodyParserURLEncoded);
// Routes
app.get('/', function(req, res){
res.json({ message: 'Spawns API' });
});
require('./app/routes/spawn.routes')(app);
// intialise server
app.listen(properties.PORT, () => {
console.log(`Server is running on ${properties.PORT} port.`);
})
The database file on ./config is the following:
var mongoose = require('mongoose');
var dbURL = require('./properties').DB;
mongoose.Promise = global.Promise;
module.exports = function(){
mongoose.connect(dbURL, { useNewUrlParser: true }, function(){
console.log('Successfully connected to database');
});
}
And the properties.js on /config is simply an object with the database URL and the port for the express server.
When I try to to a request through Postman to the URL: http://localhost:4000/list the request gets hanged and never resolves. What am I missing?
PD: SOLVED!
===========
I needed to update mongoose version on npm cause it was 3.x and needed to be 5.x in order to work well with the new methods.
Update your code little bit, Like this and check
spwanRoute.js
const express = require('express');
const router = express.Router();
const spawnCntr = require('./speanControllers');
router.get('/list', spawnCntr.getSpawns);
module.exports = router;
spwanUtils.js
const Spawns = require('../models/Spawn/spawn.dao');
const spawnUtils = {};
spawnUtils.getSpawns = (req, res) => {
try {
Spawns.get({}, (err, spawns) => {
if(err){
return res.status(400).json({ error: err });
}
return res.status(200).json({ spawns });
});
} catch (err) {
console.log(err);
return res.status(500).json({ error: 'INTERNAL_EROR' });
}
}
module.exports = spawnUtils;
Related
I am trying to insert a category in the database following the instructions of a course I am taking and I am unable to insert it with the create method. It shows ... loading in Postman and nothing happens and no error message appears on the console. Here are my files.
app.js
const express = require('express')
const mongoose = require('mongoose')
const morgan = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const expressValidator = require('express-validator')
require('dotenv').config()
//import routes
const authRoutes = require('./routes/auth')
const userRoutes = require('./routes/user')
const categoryRoutes = require('./routes/category')
// app
const app = express()
// db
mongoose.connect(process.env.DATABASE, {
useNewUrlParser: true,
useCreateIndex: true
})
.then(() => console.log('DB Connected'))
// middlewares
app.use(morgan('dev'))
app.use(bodyParser.json())
app.use(cookieParser())
app.use(expressValidator())
// routes middleware
app.use('/api', authRoutes)
app.use('/api', userRoutes)
app.use('/api', categoryRoutes)
const port = process.env.PORT || 8000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
routes/category.js
const express = require('express')
const router = express.Router()
const { create } = require('../controllers/category')
const { requireSignin} = require('../controllers/category')
const { userById } = require('../controllers/user')
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
router.param("userId", userById)
module.exports = router
controllers/category.js
const Category = require("../models/category")
const { errorHandler } = require("../helpers/dbErrorHandler")
exports.create = (req, res) => {
const category = new Category(req.body)
category.save((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
})
}
res.json({ data })
})
}
models/category.js
const mongoose = require('mongoose')
const categorySchema = new mongoose.Schema(
{
name: {
type: String,
trim: true,
required: true,
maxlength: 32
}
},
{ timestamps: true }
);
module.exports = mongoose.model('Category', categorySchema)
In order to make sure that data is actually being returned, your create function needs to be asynchronous. Adding async/await to the save function should confirm that you are properly saving the data to the database before returning.
It appears you have an error in your route setup. I assume requireSignin and create should be middleware functions.
So instead of
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
you should try this
router.post('/category/create/:userId', requireSignin, create);
// assuming 'create' is the last one, since you are ending the request there
// also assuming that 'requireSignin' is setup as middleware, calling next function
i made a very simple api using express.js. Here's the code:
var express = require('express');
var app = express();
var morgan = require('morgan');
var UserModel = require('../Models/User')
app.use(morgan('short'));
app.use(express.json());
app.get('/getAll', (req, res) => {
res.status(200).json({auth: true});
})
app.post('/addUser', (req, res) => {
const { name, email, password } = req.body;
UserModel.create({name, email, password}, (err, user) => {
if(err) return res.status(500).end({auth: false})
res.status(200).end({user});
});
});
module.exports = app;
And here's the userModel:
const mongoose = require("mongoose")
const Schema = mongoose.Schema;
const UserSchema = new Schema(
{
name: String,
email: String,
password: String,
},
{timestamps: false}
);
mongoose.model("User", UserSchema);
module.exports = mongoose.model("User");
This is the main server.js file:
var express = require('express');
var app = express();
const AuthController = require("./Controllers/AuthController");
const PORT = 3001;
app.use("/api/auth", AuthController);
app.listen(PORT, () => console.log(`Listening on port ${PORT}..`))
This is the db.js file:
const mongoose = require('mongoose');
const dbRoute = "mongodb://<user>:<password>#<stuff>/nodejs-db";
mongoose.connect(
dbRoute,
{useNewUrlParser: true}
);
So here's the problem. when i try to make a request to this api using Insomnia, the requests doesn't end. Basically Insomia starts sending the request and i have to wait like 20 secs until i get something on my express terminal. If i end the request manually i get this:
::ffff:127.0.0.1 - POST /api/auth/addUser HTTP/1.1 - - - - ms
I tried looking online but couldn't find anything useful.
I come from a django backgrond. I'm new to Node and Express js.
Edit:
The problem is only with the posts requests because whenever i make a get request it returns immediately {auth: true}.
Change your .end() to .send()
app.post('/addUser', (req, res) => {
const { name, email, password } = req.body;
UserModel.create({name, email, password}, (err, user) => {
if(err) return res.status(500).send({auth: false})
res.status(200).send({user});
});
});
I solved this problem.
Apparently the problem was that my db connection was on another file.
All i did was to move the content from the db.js file to my server.js file.
I forgot to include my db file.
I am trying to learn REST API. I created POST method but it is not working
get method is working fine in postman but post method is not working. Can anyone help me where I am missing?
I am stuck in it.
here is my code
app.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
//connect to mongoose
Genre =require('./models/genre');
Book =require('./models/book');
// Connect to Mongoose
mongoose.connect('mongodb://localhost/bookstore',{ useNewUrlParser: true });
var db = mongoose.connection;
app.get('/', (req, res) => {
res.send('Please use /api/book or /api/genres');
});
app.get('/api/genres', (req, res) => {
Genre.getGenres((err, genres) => {
if(err){
throw err;
}
res.json(genres);
});
});
app.post('/api/genres', (req, res) => {
var genre = req.body;
Genre.addGenre(genre, (err, genre) => {
if(err){
throw err;
console.log(err);
}
res.json(genre);
});
});
app.listen(3000);
console.log("running on port 3000..");
models/genre.js
const mongoose = require('mongoose');
// Genre Schema
const genreSchema = mongoose.Schema({
name:{
type: String,
required: true
},
create_date:{
type: Date,
default: Date.now
}
});
const Genre = module.exports = mongoose.model('Genre', genreSchema);
// Get Genres
module.exports.getGenres = (callback /* we can access through routes*/, limit) => {
Genre.find(callback).limit(limit);
}
//add genre
module.exports.addGenre = (genre, callback) => {
Genre.create(genre, callback);
}
get method is working fine in postman but post method is not working. Can anyone help me where I am missing?
You need to update your code accordingly:
Add in app.js:
// BodyParser middleware
const BodyParser = require(`body-parser`);
// Create application/json parser
App.use(BodyParser.json({ limit: `50mb` })); // Set request size
// create application/x-www-form-urlencoded parser
App.use(BodyParser.urlencoded({ limit: `50mb`, extended: true }));
Update API call:
app.post('/api/genres', (req, res) => {
var genre = req.body;
Genre.addGenre(genre, (err, genreDB) => {
if(err){
throw err;
console.log(err);
}
res.status(200).send(genreDB);
});
});
Hope this works for you.
If you want to access req.body in your POST handler, you'll need to use some express middleware to actually parse the request body. For example, for parsing JSON bodies, you'll need express.json middleware.
I get a message Request is not finished yet and no data will be sent, if I do patch and delete requests in my app ( the post and get request work well)
Here are my requests
In service (front, Angular 4) I create the requests
api = 'http://localhost:3000/tasks';
deleteData(id) {
return this.http.delete( this.api, id);
}
patch(data) {
return this.http.patch( this.api, data);
}
And then call them in component
this.deleteData(this.checkedItems);
this.service.patch(result.data).subscribe(d => {
this.tasks = d;
});
The service
The PATCH request get req.body via console.log - so it should works, but it doesn't
The DELETE request doesn't get any data! The req.body is empty! But I need to pass the array of ids, so I can't do it via params.
Could you please help me or give a hint? Here is my service
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
var Schema = mongoose.Schema;
const app = express();
//Middleware for CORS
app.use(cors());
app.use(express.json());
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Point static path to dist
app.use(express.static(path.join(__dirname, 'dist')));
var todoSchema = new Schema({
taskName: String,
createdAt: Date,
isDone: Boolean,
prioraty: String
}, {
collection: 'tasks'
});
var Model = mongoose.model('Model', todoSchema);
//replace when DB is online
mongoose.connect('mongodb://localhost:27017/admin').then(() => {
console.log("connected");
}).catch (() => {
console.log("not connected");
});
mongoose.connection.once('open', function () {
console.log('mongodb connected.');
});
app.patch('/tasks', function (req, res) {
console.log(req.body);
var updateObject = {
'taskName': req.body.taskName,
'isDone': req.body.isDone,
'prioraty': req.body.prioraty
}
var id = req.body._id;
Model.collection.update({_id : id}, {$set: updateObject});
});
app.delete('/tasks', function(req,res){
console.log('Delete', req.body);
var ids = [];
for (let i = 0; i < req.body.length; i ++) {
ids.push(req.body[i]._id);
}
var myquery = { _id: { $in: ids } };
Model.collection.deleteMany(myquery, function(err, obj) {
if (err) throw err;
});
});
const port = process.env.PORT || '3000';
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port, () => console.log(`API running on localhost:${port}`));
You need to close the connection when you're done handling the request, otherwise the client will wait for the server to send a response until the request timeout is reached.
app.patch('/tasks', function (req, res) {
...
Model.collection.update({_id : id}, {$set: updateObject}, function (err) {
if (err) {
console.error(err);
return res.sendStatus(500);
}
res.sendStatus(200);
});
});
app.delete('/tasks', function(req,res){
...
Model.collection.deleteMany(myquery, function(err) {
if (err) {
console.error(err);
return res.sendStatus(500);
}
res.sendStatus(200);
});
});
As for the DELETE request not having a req.body, that's because Angular 4's http client doesn't allow a body for DELETE requests. Its API for DELETE requests looks like this: this.http.delete(url, httpOptions), with no body support. You'll have to use query parameters if you need to send an array of ids. Query params does support arrays, they look something like this: https://myurl.xyz/tasks?ids[]=1&ids[]=2&ids[]=3
See https://angular.io/guide/http#url-parameters
I'm new to back-end development with node and express. i'm trying to make a back-end for a simple blog with posts and user authentication to use later in an angular 4 app.
On the "Posts" end, after testing with chrome's addon "Postman", all seems to work fine but when i started working on the "Users" side it keeps throwing off the error:
"Router.use() requires middleware function but got a ' + gettype(fn));"
When i try to run the server. The code is below:
app.js
//Imports
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const mongo = require('mongodb');
const mongoose = require('mongoose');
const passport = require('passport');
const cors = require('cors');
const config = require('./config/database');
//initialize App
var app = express();
//Setting port
var port = 3000;
//initialize cors
app.use(cors());
//Set static folder
app.use(express.static(path.join(__dirname,'../client/src')));
//initialize body parser
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
//Root route
app.get('/', function(req,res) {
res.send('Welcome to my API');
});
//Listen to port
app.listen(port, function () {
console.log('Server is running on post: ' + port);
});
//connection to DB
mongoose.connect(config.database);
mongoose.connection.on('connected', function () {
console.log('Connected to database' + config.database);
});
mongoose.connection.on('error', function (err) {
console.log('Database error' + err);
});
//Models
var Post = require('./models/post');
var User = require('./models/user');
//Routes
var postRouter = require('./routes/posts')(Post);
var userRouter = require('./routes/users')(User);
//Initialize routes
app.use('/api/posts', postRouter);
app.use('/api/users', userRouter);
models/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userModel = new Schema({
name: {type: String},
email: {type: String, required:true},
username: {type: String, required:true},
password: {type: String, required:true}
});
module.exports = mongoose.model('Users',userModel);
routes/users.js
var express = require('express');
var passport = require('passport');
var jwt = require('jsonwebtoken');
var userRoutes = function(User) {
var UserRouter = express.Router();
var userController = require('../controllers/userController')(User);
//Register
UserRouter.route('/register').post(userController.post);
//Authenticate
UserRouter.route('/authenticate').get();
//Profile
UserRouter.route('/profile').get();
};
module.exports = userRoutes;
controllers/userController.js
var userController = function(User) {
var post = function(req,res) {
var bcrypt = require('bcryptjs');
//creating new instance of model and pass the bodyParser
var user = new User(req.body);
if(!req.body.username) {
res.status(400);
res.send('Name is required');
}
else if (!req.body.password) {
res.status(400);
res.send('Password is required');
}
else if (!req.body.email) {
res.status(400);
res.send('Email is required');
}
else {
bcrypt.hash(user.password, function (err, hash) {
user.password = hash;
});
//saving in db
user.save();
//status 201 means created
res.status(201);
//send result
res.send(user);
}
};
return {
post: post
};
};
module.exports = userController;
The problem occurs when i initialize the users route with
app.use('/api/users', userRouter);
in app.js
"Router.use() requires middleware function but got a ' + gettype(fn));"
the error comes from this line :
app.use('/api/users', userRouter);
app.use need a path and a middleware function. Here your returning
a simple function, not a middleware, that's why you got the error.
in routes/users.js you just have to return the express.Router middleware function.
var express = require('express');
var passport = require('passport');
var jwt = require('jsonwebtoken');
var userRoutes = function(User) {
var UserRouter = express.Router();
var userController = require('../controllers/userController')(User);
//Register
UserRouter.route('/register').post(userController.post);
//Authenticate
UserRouter.route('/authenticate').get();
//Profile
UserRouter.route('/profile').get();
// UserRouter is a middleware function
return UserRouter;
};
module.exports = userRoutes;
see express router part here : http://expressjs.com/en/guide/routing.html