Node.js, Mongoose and Express 4.0 - Setting Modular Post Requests - javascript

Am working on a project using the mean stack.
Before setting up the client side am testing my routes using postman.
http://www.getpostman.com/
Am trying to send a post request to fetch a specific user and a post request to add a user.
This is the code....
//cons.js
'use strict';
var strg = 'mongodb://localhost/users';
module.exports={
strg:strg
}
//models.js
'use strict';
var mong = require('mongoose'),
str = require('./cons');
mong.connect(str.strg);
var pips = mong.model('pips',{
name: {type: String, required: true, index: { unique: true }},
pass: {type: String, required: true},
act:{type: Boolean}
});
module.exports = {
pips: pips
}
//user_ctrl.js
var addPips, getPipsById,
pip = require('./models').pips;
getPipsById = function(req, res){
/*pip.findOne({jina:req.params.unam}).exec(
function(err,rez){
if(err||!rez){
res.send(err);
}
res.json(rez);
})*/
pip.findOne({jina:req.body.unam}).exec(
function(err,rez){
if(err||!rez){
res.send(err);
}
res.json(rez);
})
};
addPips = function(req, res){
pip.create({
name: req.body.unam,
pass: req.body.upas,
act: false
}, function(err, rez){
if(err||!rez){
res.send(err);
}
res.send("User account created...");
})
};
module.exports = {
addPips: addPips,
getPipsById : getPipsById
}
//routes.js
'use strict';
var jada = require('./user_ctrl');
module.exports = function(app){
//app.get('/api/users/:unm',jada.getUserById);
app.post('/api/users',jada.getPipsById);
app.post('/api/users',jada.addPips);
app.all('/api/*', function(req, res) {
res.send(404);
});
};
//server.js
'use strict';
var express = require('express'),
morgan = require('morgan'),
port =process.env.PORT || 3000,
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
app = express();
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());
app.use(express.static(__dirname+"/app"));
require('./config/models');
require('./config/user_ctrl');
require('./config/routes')(app);
app.listen(port);
console.log('Magic happens on port: '+port);
Am using a post request to fetch a specific user because I am picking information from the form and not the url.
When am adding the user. I get an error message: 'validation error name and pass required'. I don't seem to see where this is coming from because I am assigning values from the form to the parameters.
Can anyone tell me what am doing wrong? Thank you...

Well, it turns out that Express Body-Parser does not know how to deal with data when the content-type is not set.
I found out from here:
Express.js req.body undefined
I use postman to test my routes before building the client side. In postman, when simulating form posts I used x-www-form-urlencoded it sets the content-type automatically.
If you are getting undefined form values, try checking if your headers (content-type) are properly set.

Related

How is the server and client supposed to interact

A little info
I got my client (localhost:8080) and my server.js (localhost:3000). I made some routes for my server.js (see the file below).
Question
Now, if I try to access the route on my server e.g. localhost:3000/users/4, I get the expected result - 4 fake users are created. However if I try to append the postfix users/4 to the client: (localhost:8080/users/4), I get an error! Cannot GET /users/4. Likewise I get an cannot GET *SOMETHING* error if I try one of the other routes.
Have I misinterpreted something? Shouldn't I be able to append the route to the client url and then get the res (respons) back again? (as long as the server is running of course, or is that not how it works?)
routes.js (I got all my routes in this one file)
var faker = require("faker");
var appRouter = function (app) {
app.get("/", function (req, res) {
res.status(200).send({ message: 'Welcome to our restful API' });
});
app.get("/user", function (req, res) {
var data = ({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
username: faker.internet.userName(),
email: faker.internet.email()
});
res.status(200).send(data);
});
app.get("/users/:num", function (req, res) {
var users = [];
var num = req.params.num;
if (isFinite(num) && num > 0 ) {
for (i = 0; i <= num-1; i++) {
users.push({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
username: faker.internet.userName(),
email: faker.internet.email()
});
}
res.status(200).send(users);
} else {
res.status(400).send({ message: 'invalid number supplied' });
}
});
};
module.exports = appRouter;
Server.js
var express = require("express");
var bodyParser = require("body-parser");
var routes = require("./routes/routes.js");
var app = express();
const server_port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
routes(app);
var server = app.listen(server_port, function () {
console.log("app running on port.", server.address().port);
});
You must be mixing up something there. When you open http://localhost:8080/users/4, then what you are doing is a SERVER request to localhost:8080 with the route users/4. The client in your scenario is a browser which is making a request to the server.
Now if your server is actually running on localhost:3000, then you must be running another server on localhost:8080. So if you want to be able to make a request to http://localhost:8080/users/4, then you need to configure your server on localhost:8080 to accept that route, not the one on localhost:3000.

Node JS - "Could not get any response" On Insert Data to Database

I'm trying to Insert some data to my database(mysql) with nodejs and I already did make some code but in postman it displays Could not get any response even though I know that I followed properly some tutorials that I watched.
Here's my code
SendOrder.js (models)
var db=require('../dbconnection');
var Task = {
addTask:function(Task,callback){
return db.query("Insert into orders ( order_id, order_no, tbl_id, menu_id, \
order_quantity, order_discount, order_type, \
order_amount, menu_name, menu_price ) values(?,?,?,?,?,?,?,?,?,?)",
[
Task.order_id, Task.order_no, Task.tbl_id, Task.menu_id,
Task.order_quantity, Task.order_discount, Task.order_type,
Task.order_amount, Task.menu_name, Task.menu_price
], callback);
},
}
module.exports=Task;
SendOrder.js (router)
var express = require('express');
var router = express.Router();
var Task = require('../models/SendOrder');
router.post('Send/', function(req, res, next){
Task.addTask(req.body,function(err,count){
console.log(req.body);
if(err)
{
res.json(err);
}
else{
res.json(req.body);
}
});
});
module.exports = router;
EDIT:
dbconnection.js
var mysql=require('mysql');
var connection=mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'opob',
});
module.exports=connection;
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var mysql = require('mysql');
var connection = require('express-myconnection')
var SendOrder = require('./routes/SendOrder'); // SendOrder
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/SendOrder', SendOrder); // SendOrder
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Go to Setting in Postman
Off the SSL certificate verification in General tab: (Second option under Request)
Off the Global Proxy Configuration and Use System Proxy in Proxy tab:
If both not work, try below code:
if(err)
{
return res.status(500).json(err);
}
else{
return res.status(200).json(req.body);
}
Hope, this may help you!
=========== EDITED ==============
Looking at your app.js file. It seems you need to use body-parser package to parse the JSON data from request.
npm install body-parser --save
body-parser extract the entire body portion of an incoming request stream and exposes it on req.body.
From whatever you have shared here are the following possibilities:
Your IP/PORT that you are trying to hit is wrong. Please cross verify them again.
The IP that you are trying to hit is not accessible from the machine where postman is installed (I added this possibility as you are using IP instead of localhost)
The third possibility would be server crashing when you hit the Send/ API. If the problem is with your code, most probably this is the reason. In this case, you can check the server console to find crash logs and stack-trace.
As #Hardik has mentioned in the comments is not a wrong URL as that would return 404.

Javascript express mongodb server not getting data from post request

I am trying to set up a very simple javascript server however I cant even properly get the data from a post request!
Here is what I am doing. I have annotated what works and what doesn't. Essentially everything except for the post request works perfectly. Unfortunately the body of the request is always empty resulting in garbage information.
const MongoClient = require('mongodb').MongoClient;
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }))
const mongoUrl = '<DBAddress Goes Here>';
MongoClient.connect(mongoUrl, (err, mongoDb) => {
if(!err) {
db = mongoDb;
console.log("Connected correctly to server");//This always happen successfully
}
});
app.listen(80);
app.get('/test', function(req, res) {
res.json({ data1: 11, data2: 4, data3: 9 }); //This always works!
});
app.post('/update', function(req, res) {
const params = req.body;
console.log(req.body);//Empty
console.log("Parameters");
const newReport = {
id: params.id,
data: params.data
};
console.log(newReport);//Nothing is put in here
});
I am testing this post request in Postman with website.com/update as the address and the proper fields in the body part of the post.
You need to parse request body in order to get the body in req.body.
As you are already using body-parser package just add the following line after your urlEncoded middleware. and remember the order of middleware matters in the express.
app.use(bodyParser.json());
add above line right after this
app.use(bodyParser.urlencoded({ extended: false }))
And make sure that you are sending data in the JSON format as by default postman send data in plain format

Declare session with express node.js and mongoose

I'm doing an application with Node.js, Express, MongoDB (mongoose), I'm trying to make the database connection in a separate file from server.js, but I'm having a hard time with connect-mongo.
First in my server.js I had this:
/* jshint esversion: 6 */
'use strict';
let express = require('express');
const db = require('./app/config/db');
const routes = require('./app/routes/routes');
const users = require('./app/routes/users');
let app = express();
const conn = db.connect();
app.set('views', path.join(__dirname, 'app/views'));
app.set('view engine', 'hbs');
...
app.use('/', routes);
app.use('/users', users);
app.listen(3000);
module.exports = app;
This only handle the application routes, and the application server, then I had the next folder structure for my project:
myApp
|___app
|___bin
|___config
|___credentials.js
|___db.js
|___controllers
|___routes
|___views
|___node_modules
|___package.json
|___server.js
Welll insidde config folder I had two javascripts that handle the connection to the database, in the credentials.js literally only had the credentials for the access of the database.
Then my problem is inside the db.js, next I show you the file:
/* jshint esversion: 6 */
'use strict';
let mongoose = require('mongoose'),
async = require('async'),
express = require('express');
const credentials = require('./credentials');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
let db = mongoose.connection,
app = express();
exports.connect = function(done){
const connection = mongoose.connect(credentials.host, credentials.database, credentials.port, credentials.db);
db.on('error', (error =>{
console.log("Error estableciendo la conexion");
process.exit(1);
}));
db.on('open', (argv)=>{
db.db.listCollections().toArray((err, collections)=>{
collections.forEach(x => console.log(x));
});
});
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ dbPromise: db })
}));
}
I got the next error:
Error with nodemon server.js
Do you know how to initiate connect-mongo using this project structure?
By the way, in the credentials.js file I setup Bluebird as my promise library.
In advance thank you!
The problem was, like #MananVaghasiya said, that my variable db was not a Promise, this is a bug inside the mongoose project, so I changed the connection type to a basic uri connection with mongoose and then after the query of login I set the session.
The code it's looking like this at this time, so thank you for your time.
module.exports.login = (req, res)=>{
const mail = req.body.mail.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
password = req.body.password;
user.findOne({$and:[{'mail' : mail}, {'password': password}]}, (err, user)=>{
if(err){
res.send(err);
} else {
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ mongooseConnection: db }),
saveUnitialized: true,
resave: false,
cookie:{
path: "/"
},
name: user.role
}));
return user;
}
});
};

req.user undefined after twitter authentication using express sever, passport.js

There are many questions relating to getting a req.user undefined after social authentication, but I found none which could help me.
I have been able to successfully use the example for using passport for twitter authentication: https://github.com/passport/express-4.x-twitter-example. I tried to follow this pattern as closely as possible but cannot seem to get it to work.
Specifically, I am able to successfully authenticate, but the req.user is undefined. This makes no sense to me as my user data was returned no problem from the example.
I'm not inclined to believe this is a middleware problem (as it has been for others) as the middleware is the same as that used in the example. It could be something about having multiple domains, but I'm not sure what. All of this is being done on the localhost.
In Twitter, the app is set up so that
website is: 127.0.0.1:3000/signin
and the
callback url is: 127.0.0.1:2999/auth/twitter/return
As you can tell, my client is working on port 3000 and it is making calls to a server running on port 2999.
To briefly walk you through the code, the client on 127.0.0.1:3000/signin has a button which links to 127.0.0.1:2999/auth/twitter, thus initiating the authentication request. Under the hood, the express server is created in server/index.js--server. This imports the routes in routes/index.js, some of which the controller authenticate.js handles. As you can see, the oauth twitter request is made in authenticate.js. Again, authentication proceeds successfully, I am redirected to 127.0.0.1:3000/search. However, as you can see in this.twitter_callback, I am printing the req.user and it is undefined.
Please note that I have redacted the consumer key/secret from my code.
server/index.js
var cors = require('cors')
var bodyParser = require('body-parser')
var express = require('express');
var app = express();
var http = require('http').Server(app)
var io = require('socket.io')(http)
// NOT SURE WHY I NEED TO GO BACK 3 FOLDERS TO GET TO PORT_CONFIG
var port = require("../port_config.json").server_port;
var PORT = Number(process.env.PORT || port);
var routes = require('./routes/index.js')
var database = require('./database/db.js')
var db = new database()
app.use(cors()); // middleware that allows cross-platform requests
app.use(bodyParser.json());
db.dbConnect(function(err,db_instance){
// routes
routes(app, db_instance, io)
// send user polls on connection
// TEMPORARY (WILL BE GRABBED ON LOGIN)
var user = null // WILL BE SET AFTER LOGIN
io.on('connection', function(socket) {
var places_attending = db_instance.collection('places_attending')
places_attending.find({}).toArray(function(err,docs){
var places_user_attending = docs.map(doc => {
if (doc.attending.indexOf(user) !== -1) {
return {
id: doc.id,
name: doc.name,
num_attending: doc.attending.length
}
}
})
socket.emit('places_user_attending', places_user_attending);
})
})
})
http.listen(PORT, function () {
console.log('Backend server listening at http://localhost:' + PORT);
})
module.exports = http
routes/index.js
var Search = require('../controllers/search.js')
var Add = require('../controllers/add.js')
var Authenticate = require('../controllers/authenticate.js')
module.exports = function(app, db, io) {
var search = new Search(db, io)
var add = new Add(db, io)
var authenticate = new Authenticate(app)
app.route('/api/search')
.post(search.search_yelp)
app.route('/api/add')
.post(add.add_attendee)
app.route('/auth/twitter')
.get(authenticate.twitter_authentication)
app.route('/auth/twitter/return')
.get(authenticate.twitter_callback)
}
authenticate.js
function authenticate(app) {
var passport = require('passport');
var Strategy = require('passport-twitter').Strategy;
// Configure the Twitter strategy for use by Passport.
passport.use(new Strategy({
consumerKey: REDACTED,
consumerSecret: REDACTED,
callbackURL: 'http://127.0.0.1:2999/auth/twitter/return'
},
function(token, tokenSecret, profile, cb) {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
return cb(null, profile);
}));
// Configure Passport authenticated session persistence.
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
app.use(passport.session());
this.twitter_authentication = passport.authenticate('twitter')
this.twitter_callback = (
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log('REQ.USER OBJECT: ' + req.user)
res.redirect('http://127.0.0.1:3000/search');
}
)
}
module.exports = authenticate
Any help would be greatly, greatly appreciated.
The problem was in how my twitter_callback route was specified.
If I change the callback to this:
this.twitter_callback = app.get('/auth/twitter/return',
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log(req.user)
res.redirect('http://127.0.0.1:3000/search');
})
everything works fine. I think this has something to do with the middleware not being applied correctly the initial way I wrote it. Not exactly sure how I would rewrite it to export it, without using app.get in the twitter_callback though

Categories

Resources