NodeJS - Why POST after GET doesn't work in express app? - node.js

This is app have only GET /test, it doesn't have POST /test yet. I'm uploading binary file 1.dat to it and it should return answer with '404', but seems I'm recieving ECONNRESET error instead.
var express = require('express');
var app = express();
var expect = require('expect.js');
var request = require('supertest');
var router = express.Router({
caseSensitive: true,
strict: true
});
router.get('/', function(req, res, next) {
res.send('test');
});
app.use('/test', router);
app.use(function(req, res, next) {
res.send('404');
});
Promise.resolve().then(function() {
var agent = request(app);
return new Promise(function(resolve, reject) {
agent
.get('/test')
.expect(200)
.end(function(err) {
if (err) {
return reject(err);
}
resolve(agent);
});
});
}).then(function(agent) {
return new Promise(function(resolve, reject) {
agent
.post('/test')
.attach('tmp', new Buffer([1, 2, 3]), '1.dat')
.expect(404)
.end(function(err, res) {
if (err) {
return reject(err);
}
resolve();
});
});
}).then(function() {
process.exit(0);
}).catch(function(err) {
console.log(err.stack);
process.exit(1);
});
But why it throws an error when validating .expect(404):
[TypeError: Cannot read property 'status' of undefined]

You don't send a status 404 but a string in your body.
app.use(function(req, res, next) {
res.status(404).end();
});

Related

authenticate.getToken is not a function on node.js v12.18.2

I am receiving an authenticate.getToken is not a function error.
var express = require('express');
const bodyParser = require('body-parser');
var User = require('../models/user');
const passport = require('passport');
var authenticate = require('../authenticate');
var router = express.Router();
router.use(bodyParser.json());
/* GET users listing. */
router.get('/', function (req, res, next) {
res.send('respond with a resource');
});
router.post('/signup', (req, res, next) => {
User.register(
new User({ username: req.body.username }),
req.body.password, (err, user) => {
if (err) {
res.statusCode = 500;
res.setHeader('Content-Type', 'application/json');
res.json({ err: err });
} else {
passport.authenticate('local')(req, res, () => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({ success: true, status: 'Registration Successful!' });
});
}
}
);
});
router.post('/login', passport.authenticate('local'), (req, res) => {
var token = authenticate.getToken({ _id: req.user._id });
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json({ success: true, token: token, status: 'You are successfully logged in!' });
});
router.get('/logout', (req, res) => {
if (req.session) { req.session.destroy();
res.clearCookie('session-id');
res.redirect('/');
} else {
var err = new Error('you are not logged in');
err.status = 403;
next(err);
}
});
module.exports = router;
The error simply means that authenticate.getToken is not a function. have you exported correctly in your authenticate.js file? It may be worth posting your authenticate.js file to your OP.
It should look something like this for it to work:
authenticate.js
module.exports = {
getToken: function() {
// code here
}
}

Problem returning data from database (db.js) to node (app.js)

I am trying to request data from a postgres database in node.js via a post request. Eventually this data will be sent a react frontend.
I am getting correct data from database but can't seem to return this data to app.js (I'm a bit of a node.js noob). I have two files app.js and db.js
Here is app.js
const express = require('express');
const morgan = require('morgan');
const helmet = require('helmet');
const cors = require('cors')
const db = require('./db')
const bodyParser = require('body-parser')
const middlewares = require('./middlewares');
const app = express();
app.use(cors());
app.use(morgan('dev'));
app.use(helmet());
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(bodyParser.urlencoded({ extended: false }))
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
next();
});
app.get('/api', (req, res) => {
res.send({ express: 'Server online' });
});
app.post('/layer', (req, res, next) => {
var layer = req.body.menu;
var geometry = db.layer(layer);
console.log(geometry);
res.set('Content-Type', 'application/json')
//const body = res.body()
});
app.use(middlewares.notFound);
app.use(middlewares.errorHandler);
module.exports = app;
Here is db,js
const { Pool, Client } = require('pg')
const connection = new Pool({
user: 'postgres',
host: 'localhost',
database: 'dbtemp',
password: 'password',
port: 5432,
max: 20,
connectionTimeoutMillis: 2000,
})
connection.connect(function(err) {
if (err) throw err;
});
connection.on('connect', () => {
console.log("connected to database on port: " );
});
module.exports = {
layer: function(layer) {
connection.query('SELECT ST_AsGeoJSON(geom) FROM nzta_centrelines', (err, result) => {
if (err) {
return console.error('Error executing query', err.stack)
}
var geometry = result.rows[0].st_asgeojson;
console.log(geometry);
return result;
})
}
}
I am getting the correct data logged to console from db.js
Output:
Listening: http://localhost:5000
connected to database on port:
Promise { undefined }
connected to database on port:
{"type":"MultiLineString","coordinates":[[[1797202.15,5753380.18,0],[1797200.87,5753384.48,0],[1797198.16,5753393.62,0],[1797197.78,5753404.37,0],[1797200.38,5753428.48,0],[1797217.82,5753566.48,0],[1797225.98,5753623.6,0],[1797227.09,5753645.86,0],[1797225.98,5753665.52,0],[1797223.38,5753684.07,0],[1797213.95,5753717.71,0]]]}
How do I get query result to app.js and send to webpage (React front end). I'm guessing it needs a callback when data is ready?
You may want to consider using a promise or a callback
Promise approach
db.js
...
module.exports = {
layer: function(layer) {
return new Promise((resolve, reject) => {
connection.query('SELECT ST_AsGeoJSON(geom) FROM nzta_centrelines', (err, result) => {
if (err) {
console.error('Error executing query', err.stack)
return reject(err);
}
var geometry = result.rows[0].st_asgeojson;
console.log(geometry);
return resolve(result);
})
})
}
}
app.js
...
app.post('/layer', async (req, res, next) => {
var layer = req.body.menu;
var geometry = await db.layer(layer);
console.log(geometry);
res.set('Content-Type', 'application/json')
//const body = res.body()
});
Callback approach
db.js
module.exports = {
layer: function(layer, cb) {
connection.query('SELECT ST_AsGeoJSON(geom) FROM nzta_centrelines', (err, result) => {
if (err) {
console.error('Error executing query', err.stack)
return cb(err)
}
var geometry = result.rows[0].st_asgeojson;
console.log(geometry);
return cb(null, geometry);
})
}
}
app.js
...
app.post('/layer', (req, res, next) => {
var layer = req.body.menu;
db.layer(layer, (err, geometry) => {
if (err) throw err;
console.log(geometry);
res.set('Content-Type', 'application/json')
//const body = res.body()
});
});

Express.js nested routes without parameters

I have a Express server resolving GET /companies/:id/populate/. Now, I would like to setup GET /companies/populate/ (without the :id). However, I can't make this route to work. If I try, for example, GET /companies/all/populate/, it works, so it seems the pattern for an Express route is path/:key/path/:key.
Is this true? Thanks!
Edit: Adding code.
server.js
'use strict';
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cors = require('cors');
var mongoUri = 'mongodb://localhost:27017';
mongoose.connect(mongoUri);
var db = mongoose.connection;
db.on('error', function() {
throw new Error('Unable to connect to database at' + mongoUri);
});
// runs Express
var app = express();
// uses Cors
app.use(cors());
// uses bodyParser
app.use(bodyParser.json());
// requires Mongo models
require('./models');
// includes routes.js, passing the object 'app'
require('./routes')(app);
// listens for connections on port 3000
app.listen(3000, function() {
console.log("Express started on Port 3000");
});
routes.js
module.exports = function(app) {
// thumbs up if everything is working
app.get('/', function(req, res, next) {
res.send('👍');
console.log('Server Running');
res.end();
});
// companies
var companies = require('./controllers/companies');
app.get('/companies', companies.findAll);
app.get('/companies/:id', companies.findById);
app.get('/companies/:id/populate', companies.populate);
app.get('/companies/populate', companies.populateAll);
app.post('/companies', companies.add);
app.patch('/companies/:id', companies.patch);
app.delete('/companies/:id', companies.delete);
};
/controllers/companies.js
var mongoose = require('mongoose');
Company = mongoose.model('Company');
// GET /companies
// status: works, needs error handling
exports.findAll = function(req, res) {
Company.find({}, function(err, results) {
return res.send(results);
});
};
// GET /companies/:id
// status: works, needs to check error handling
exports.findById = function(req, res) {
var id = req.params.id;
Company.findById(id, function(err, results) {
if (results) res.send(results);
else res.send(204);
});
};
// POST /companies
// status: works, needs error handling
exports.add = function(req, res) {
Company.create(req.body, function(err, results) {
if (err) {
return console.log(err)
} else {
console.log('company created');
}
return res.send(results);
});
};
// PATCH /companies/:id
// status: works, needs error handling
exports.patch = function(req, res) {
var id = req.params.id;
var data = req.body;
Company.update( { '_id' : id }, data, function(err, numAffected) {
if (err) return console.log(err);
return res.send(200);
});
};
// DELETE /companies/:id
// status: works, needs error handling, make sure that we are sending a 204 error on delete
exports.delete = function(req, res) {
var id = req.params.id;
Company.remove({ '_id': id }, function(results) {
console.log('deleted ' + id); // tester
return res.send(results);
});
};
// GET /companies/:id/populate
exports.populate = function(req, res) {
var id = req.params.id;
Company
.findOne({ _id: id })
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};
// GET /companies/populate
exports.populateAll = function(req, res) {
Company
.find({})
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};

Authentication failure when using express-session

I wrote some code for login authentication using express. I used express-session. Code sample is
// Authentication and Authorization Middleware
var auth = function(req, res, next) {
if (req.session && req.session.admin) {
return next();
} else {
console.log("failed");
return res.sendStatus(401);
}
}
// Login endpoint
router.post('/login', function (req, res) {
var collection = db.get("login");
collection.find({}, function(err, details) {
if (!req.body.username || !req.body.password) {
res.send('login failed');
} else if(req.body.username === details[0].name && req.body.password === details[0].password ) {
req.session.admin = true;
var data = {
"status": "success",
"message": "login success!"
}
res.send(data);
} else {
var data = {
"status": "failure",
"message": "login failed"
}
res.send(data);
}
});
});
// Logout endpoint
router.get('/logout', auth, function (req, res) {
req.session.destroy();
res.send("logout success!");
});
//Getting Details endpoint
router.get("/data", auth, function(req, res) {
var collection = db.get('details');
collection.find({}, function(err, details){
if (err) throw err;
res.json(details);
});
});
After successful login req.session.admin is set to true. But, at Authentication middleware (auth), it is sending 401 status. Please help me solve this problem.
code:
//app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var getDetails = require('./routes/getDetails');
var app = express();
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
// view engine setup
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.cookieParser());
app.use(express.static(path.join(__dirname, 'routes')));
app.use(express.session({
secret: '2C44-4D44-WppQ38S',
resave: true,
saveUninitialized: true
}));
app.use('/getDetails',getDetails);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
//app.listen(3001);
module.exports = app;
//getDetails.js
var express = require('express');
var router = express.Router();
var monk = require('monk');
var db = monk('localhost:27017/saidb');
// Login endpoint
router.post('/login', function (req, res) {
var collection = db.get("login");
//var data;
collection.find({}, function(err, details) {
//res.json(details);
if (!req.body.username || !req.body.password) {
res.send('login failed');
} else if(req.body.username === details[0].name && req.body.password === details[0].password ) {
req.session.admin = true;
var data = {
"status": "success",
"message": "login success!"
}
res.send(data);
} else {
var data = {
"status": "failure",
"message": "login failed"
}
res.send(data);
}
});
});
var auth = function(req, res, next) {
if (req.session && req.session.admin) {
console.log("success");
return next();
} else {
console.log("failed");
return res.sendStatus(401);
}
}
// Logout endpoint
router.get('/logout', auth, function (req, res) {
req.session.destroy();
res.send("logout success!");
});
//Getting Details endpoint
router.get("/data", auth, function(req, res) {
var collection = db.get('details');
collection.find({}, function(err, details){
if (err) throw err;
res.json(details);
});
});
//Get details by ID endpoint
router.get("/data:id", auth, function(req, res) {
var collection = db.get('details');
collection.find({id: parseInt(req.params.id)}, function(err, details){
if (err) throw err;
res.json(details);
});
});
//Adding Details endpoint
router.post("/data", auth, function(req, res) {
var collection = db.get("details");
collection.count({id : parseInt(req.body.id)},function(err,count){
if(!err){
if(count>0){
//send the response that its duplicate.
//console.log(errorororrrroror);
res.send("r");
}
}
});
console.log("request", req.body);
collection.insert({ id: parseInt(req.body.id),
website: req.body.website,
subtitle: req.body.subtitle,
url: req.body.url },
function(err, details) {
if(err) throw err;
res.json(details);
})
});
//Editing Details endpoint
router.put("/data", auth, function(req,res){
var collection = db.get("details");
collection.update({id: parseInt(req.body.id)},
{id: parseInt(req.body.id), website: req.body.website, subtitle: req.body.subtitle, url: req.body.url},
function(err, details){
if(err) throw err;
res.json(details);
})
});
//Deleting details endpoint
router.delete("/data", auth, function(req,res){
var collection = db.get("details");
collection.remove({id: parseInt(req.body.id)}, function(err, details){
if(err) throw err;
res.json(details);
})
});
module.exports = router;
Use these lines in your server file at top after express object like this
var app = express();
app.use(express.cookieParser());
app.use(express.session({secret: "sdsddsd23232323" }));

Node passing parameters through Q service promise

I have a middleware setup in node to perform a task and call next upon success or failure. The task is called after an initial promise block runs. It is called in the .then function:
var Q = require('q');
var dataPromise = getCustomerId();
dataPromise
.then(function(data) {
getGUID(req, res, next);
}, function(error) {
console.log('Failure...', error);
});
};
The server hangs though because the (req,res,next) parameters are all undefined when in the context of the .then function.
Here is getCustomerId function:
var getCustomerId = function() {
var getCustomerIdOptions = {
options...
};
var deferred = Q.defer();
request(getCustomerIdOptions, function(err,resp,body){
if(err){
deferred.reject(err);
console.log(err);
return;
}else{
deferred.resolve(body);
}
});
return deferred.promise;
};
What would be the correct way to pass these parameters to the function called in the .then block?
EDIT:
The (req,res,next) parameters are from the outer function and are accessible when getGUID(req,res,next) is called outside of the .then() block.
var assureGUID = function(req, res, next) {
if(app.locals.guid){
next();
return;
}
var dataPromise = getCustomerId();
dataPromise
.then(function(data) {
getGUID(req, res, next)
}, function(error) {
console.log('Failure...', error);
}).;
};
Not sure what you are trying to do exactly, but you can call your promise function inside a express common middleware function like the next sample.
var express = require('express');
var $q = require('q');
var request = require('request');
var app = express();
// Middleware 1
app.use( function(req, res, next) {
console.log('i\'m the first middleware');
getCustomerId().then( function(body) {
console.log('response body', body);
return next();
},
function(err) {
console.log('Error on middlware 1: ', err);
});
});
// Middleware 2
app.use( function(req, res, next) {
console.log('i\'m the second middleware');
return next();
});
app.get('/', function(req, res) {
res.send('hi world');
});
app.listen(3000);
// Your custom function definition
function getCustomerId() {
var deferred = $q.defer();
request('http://someurltogetjsondata/user/id', function(err, resp, body) {
if(err) return deferred.reject(err);
deferred.resolve(body);
});
return deferred.promise;
}
I hope this helps a little, good luck.

Resources