Node.JS and Postgres Search Bar - javascript

Im trying to create a search bar that will query and display the data from my own Postgres database. I have a search bar on my screen, and I think I am connected to my database, but i cannot get any results to show up. Any help would be appreciated. Im still quite new to using node.js and developing tools such as this. When i submit my search, i receive a 404 error message.
Index.js
const express = require('express');
const router = express.Router();
const pg = require('pg');
const path = require('path');
const connectionString = process.env.DATABASE_URL || 'postgres://postgres:postgres#localhost:5432/todo';
router.get('/', (req, res, next) => {
res.sendFile(path.join(
__dirname, '..', '..', 'client', 'views', 'index.html'));
});
router.get('/api/v1/todos', (req, res, next) => {
const results = [];
// Get a Postgres client from the connection pool
pg.connect(connectionString, (err, client, done) => {
// Handle connection errors
if(err) {
done();
console.log(err);
return res.status(500).json({success: false, data: err});
}
// SQL Query > Select Data
const query = client.query('SELECT name FROM world_heritage_sites.caravanserai ORDER BY iso ASC;');
// Stream results back one row at a time
query.on('row', (row) => {
results.push(row);
});
// After all data is returned, close connection and return results
query.on('end', () => {
done();
return res.json(results);
});
});
});
App.js
const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const routes = require('./server/routes/index');
// var users = require('./routes/users');
const app = express();
// view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'html');
// 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(cookieParser());
app.use(express.static(path.join(__dirname, 'client')));
app.use('/', routes);
// app.use('/users', users);
// catch 404 and forward to error handler
app.use((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((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: {}
});
});
module.exports = app;
HTML
<!DOCTYPE html>
<html ng-app="nodeTodo">
<head>
<title>Todo App - with Node + Express + Angular + PostgreSQL</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="/search.js" type="text/javascript"></script>
<script src="/search.js"></script>
<script src="//code.jquery.com/jquery-2.2.4.min.js" type="text/javascript"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" type="text/javascript"></script>
</head>
<body ng-controller="mainController">
<div class="container">
<div class="header">
<h1>SuckySearchBar</h1>
<hr>
<h1 class="lead">Designing Search Bars Suck This Never Works</h1>
</div>
</body>
<body ng-controller="searchController">
<div class="container">
<div class="search-box">
<input class="search" type="text" placeholder="Search" id="search" method='GET' autocomplete="on" onkeyup="search();">
<table class="result table-bordered" id="search"></table>
<script>
function searchinput(){
$.ajax({
type: 'GET',
url: '/api/v1/todos' + searchinput,
success: function(result){
window.location.reload(true);
}
})
}
</script>
</div>
</body>
</html>
Search.js
function search(search_string, func) {
pool.query(
"SELECT name FROM world_heritage_sites.caravanserai ORDER BY iso ASC",
[search_string],
function(err, result) {
if(err) {
func([])
} else {
func(result.rows)
}
}
);
}
module.export = search;

first of all, congrats for starting a new studies task! But let's solve this issue, shall we?
1 - My tip for you, is that before you even start to worry about the frontend, let's make sure that our service is running fine, and we shall test it on the server-side only. "I think I am connected to my database", we cannot proceed if we think something is going on fine, we need to make sure!
2 - We need our service running, that`s the only way we can get our DB connected. So for now, we forget about the interface and DB, let's focus on the service:
Inside your "app.js" you are trying to import your routes right? By doing
const routes = require('./server/routes/index');
But in order to do that, you need to export those routes before, then go to your "index.js" file and add "module.exports = router". Now you can use your router imported inside your "app.js" file!
Stays like this:
const express = require('express');
const router = express.Router();
const pg = require('pg');
const path = require('path');
const connectionString = process.env.DATABASE_URL || 'postgres://postgres:postgres#localhost:5432/todo';
Almost there, our service needs to listen to some port now
router.get('/', (req, res, next) => {
res.sendFile(path.join(
__dirname, '..', '..', 'client', 'views', 'index.html'));
});
router.get('/api/v1/todos', (req, res, next) => {
console.log("HAHAHAHAHA")
const results = [];
// Get a Postgres client from the connection pool
pg.connect(connectionString, (err, client, done) => {
// Handle connection errors
if(err) {
done();
console.log(err);
return res.status(500).json({success: false, data: err});
}
// SQL Query > Select Data
const query = client.query('SELECT name FROM world_heritage_sites.caravanserai ORDER BY iso ASC;');
// Stream results back one row at a time
query.on('row', (row) => {
results.push(row);
});
// After all data is returned, close connection and return results
query.on('end', () => {
done();
return res.json(results);
});
});
});
module.exports = router;
Now our application needs to listen to some port. I don't have access to your folder structure, that's why I will work the idea using only these two files you presented us. Inside your "app.js" you got tell your application to serve using one port, you can do that by typing
"app.listen(8000, () => console.log('listening'))
"
since you are exporting your app, you can import and use it anywhere you'd like, but I told you already, I will work the idea restricted to the files you showed us, that's why your "app.js" would be like this
check this Docs before : https://node-postgres.com/features/connecting
const express = require('express');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const routes = require('./index');
// var users = require('./routes/users');
const app = express();
// view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'html');
// uncomment after placing your favicon in /public
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'client')));
app.use('/', routes);
// app.use('/users', users);
// catch 404 and forward to error handler
app.use((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((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: {}
});
});
app.listen(8000, () => console.log('listening'))
module.exports = app;
Ok, now our service is running, go to your terminal and type: node app.js
it should print "listening" in your shell.
Now try to access http://localhost:8000/api/v1/todos in your browser, it should print an error "pg.connect is not a function"
That's because you are not using the lib the right way, try something like this
const express = require('express');
const router = express.Router();
const path = require('path');
const { Pool, Client } = require('pg')
const connectionString = 'postgres://postgres:postgres#localhost:5432/todo'
const client = new Client({
connectionString: connectionString,
})
client.connect()
router.get('/', (req, res, next) => {
res.sendFile(path.join(
__dirname, '..', '..', 'client', 'views', 'index.html'));
});
router.get('/api/v1/todos', (req, res, next) => {
const results = [];
client.query('SELECT name FROM world_heritage_sites.caravanserai ORDER BY iso ASC;', (err, res) => {
console.log(err, res)
client.end()
})
});
module.exports = router;
But remember, you need to have your Postgres service running in your localhost to connect using this connection string you are using. If you configured your Postgres service and db the right way, it should work fine, then you just need to call your route "localhost:8000/api/v1/todos" in your interface.
Actually there are a lot of things you should check in your code, and maybe it's good if you get some background before start this project. Try some tutorials for beginners on youtube and check other dev's code. Good Luck and Good code dude!
I hope I gave you at least a little help :)

I think what #Molda is saying is that you should change methods=['GET'] to method='GET'. Can you post the surrounding html as well?
EDIT
Ok, so I think you are confusing the javascript running on your server and the javascript running in the browser. If you are going to call search() from the onKeyUp() event handler Then it is going to run in the browser. Since it is going to run in the browser, it does not have the ability to access postgres directly. What it should do is make an ajax request to a route on the server that provides it with the search results as json (similar to what you did with /api/v1/todos you could define /api/v1/search), which it then renders on the page somehow (perhaps with jquery). In this case, you shouldn't even need to define method on your input.

Related

app.use("/uploads/images", express.static(path.join("uploads", "images"))); This route does not work in node.js app

This Route below Does not work in my node.js server app API deployed in server for fetching image
app.use("/uploads/images", express.static(path.join("uploads", "images")));
On the other hand, the path below just working fine
app.use("/uploads", express.static('uploads'));
I don't know what I am doing wrong in I want the first one to categorize my images better.
In Case You want to take a look into my
App.js
const fs = require("fs"); //Node Built in file Sytem module
const path = require("path"); //Path Module built in
const mongoose = require("mongoose");
const express = require("express");
const placesRoutes = require("./routes/places-routes");
const usersRoutes = require("./routes/users-routes");
const bodyParse = require("body-parser");
const HttpError = require("./Models/http-error");
const { application } = require("express");
// All the Imports Above
const app = express();
// Using Middleware
app.use(bodyParse.json());
app.use("/uploads", express.static('uploads'));
app.use("/uploads/images", express.static(path.join("uploads", "images")));
//Middleware for Handling CORS Error in Frontend
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Orgin, X-Requested-With, Content-Type, Accept, Authorization"
);
res.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE");
next();
});
// Using Route attaching Middleware
app.use("/api/places", placesRoutes);
app.use("/api/users", usersRoutes);
app.use((req, res, next) => {
const err = new HttpError("This Route does not exist ", 404);
throw err;
});
app.use((error, req, res, next) => {
if (req.file) {
fs.unlink(req.file.path, (err) => {
console.log(err);
});
}
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || "An unknown error occupied !" });
});
mongoose
.connect(
`${process.env.DB_URL}`
)
.then(() => {
console.log("Database Connected");
app.listen();
})
.catch((error) => {
console.log(error);
});
You need to use __dirname prefix. Instead of this:
app.use("/uploads/images", express.static(path.join("uploads", "images")));
Try this:
app.use(
"/uploads/images",
express.static(path.join(__dirname, "uploads", "images"))
);
See my cat example image:
https://codesandbox.io/p/sandbox/node-js-express-static-path-fn8l16
*EDIT 1
Express documentation mentions this:
However, the path that you provide to the express.static function is relative to the directory from where you launch your node process. If you run the express app from another directory, it’s safer to use the absolute path of the directory that you want to serve:
const path = require('path')
app.use('/static', express.static(path.join(__dirname, 'public')))

How to debug EJS

There are several answers for this question, but they're all several years old and no longer relevant/safe to use.
Since EJS is rendered as html in the browser, there's no way to inspect it in the browser dev tools
The EJS.co site says that the errors/logs should show in the terminal just like node errors, but that's not the reality for me, somehow.
I used the command npx express-generator to bootstrap my project, and I'm wondering if there isn't a debugger of some kind in there that is overriding how EJS is supposed to send errors?
I say this because when EJS has an error, the only thing my terminal shows is something like GET /users/dashboard 500 26.5 ms with nothing else. And then of course the browser shows the default message for 500 errors, which isn't helpful.
I'll throw in my app.js in case someone smarter than me can see the issue there:
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const rfs = require('rotating-file-stream')
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const mongoose = require('mongoose');
require('mongoose-type-url');
// const serveFavicon = require('serve-favicon');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const expressSession = require('express-session');
const methodOverride = require('method-override');
const expressSanitizer = require('express-sanitizer');
const sgMail = require('#sendgrid/mail');
// create a rotating write stream
const accessLogStream = rfs.createStream('access.log', {
interval: '1d', // rotate daily
path: path.join(__dirname, 'log')
});
const User = require('./models/user');
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const formsRouter = require('./routes/forms');
const companiesRouter = require('./routes/companies');
const locationsRouter = require('./routes/locations');
const app = express();
if (app.get('env') == 'development'){ require('dotenv').config(); };
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
//connect to database
mongoose.connect(process.env.DATABASE_URL,{
useNewUrlParser:true,
useUnifiedTopology:true,
useFindAndModify: false,
useCreateIndex:true
}).then(() => {
console.log('Connected to Mongo DB')
}).catch(err => {
console.log('error: ',err.message)
});
// view engine setup
//use ejs-locals for all ejs templates
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev', { skip: function (req,res) { return res.statusCode < 400} }));
app.use(logger('common', { stream: accessLogStream }));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(methodOverride("_method"));
app.use(expressSanitizer());
var expiryDate = new Date(Date.now() + 60 * 60 * 1000 * 6) // 6 hours
app.use(expressSession({
secret:"surfs up brah",
resave:false,
saveUninitialized:false,
name: 'sessionId',
secure:true,
httpOnly:true,
expires: expiryDate
}));
app.use(passport.initialize());
app.use(passport.session());
app.disable('x-powered-by');
app.use(function(req, res, next){
res.locals.currentUser = req.user;
next();
});
// CHANGE: USE "createStrategy" INSTEAD OF "authenticate"
passport.use(User.createStrategy({usernameField:'personalEmail'}));
// use static authenticate method of model in LocalStrategy
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
//set local variables middleware
app.use(async function (req,res,next) {
if (app.get('env') == 'development'){ req.user = await User.findOne({firstName: 'potato'}); };
res.locals.currentUser = req.user;
//set default page title if one is not specified
res.locals.title='Custom Forms';
//set success flash message
res.locals.success = req.session.success || "";
//delete flash message after sending it to the page so it doesn't show again
delete req.session.success;
//set error flash message
res.locals.error = req.session.error || "";
//delete flash message after sending it to the page so it doesn't show again
delete req.session.error;
//continue on to the next function in the middlware/route chain
next();
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/forms', formsRouter);
app.use('/companies', companiesRouter);
app.use('/locations', locationsRouter);
// 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');
});
const { seedDatabase, clearDatabase, seedDefaultQuestions, clearRecentItems} = require('./seeds.js');
async function databaseInit() {
await clearRecentItems();
// await seedDefaultQuestions();
// await clearDatabase();
await User.register({firstName: 'potato', lastName:'head',username:'potatohead', personalEmail:'test#test.com', role:'Owner'},'password');
// await seedDatabase();
}
databaseInit();
let port = process.env.PORT;
if (port == null || port == "") {
port = 8080;
}
app.listen(port, () => {
console.log("server has started, listening on port "+port);
});
module.exports = app;
Here's an example route:
app.get('/dashboard', (req,res) => {
const currentCompany = Company.findById(req.params.id);
res.render('../views/company/profile', {currentCompany});
}
And some sample EJS:
<html>
<body>
<h1><%= currentCompany.name %></h1>
</body>
</html>
Now say I didn't wrap the findById call in a try block and it didn't find a document, then tried to render the page using an undefined or null object. The EJS file wouldn't have anything to which to refer for currentCompany.name (by the way, I do indeed try/catch and handle errors).
This is where the terminal just logs the simple 500 error, and refuses to load anything at all.
Another example of issues I've had with EJS:
<html>
<body>
<&- include('../../partials/header) %>
</body>
</html>
Here, it would throw the exact same 500 error because I went up one too many folders in the path for that partial. Absolutely nothing else shown anywhere.
Thanks to #LawrenceCherone, the issue is the default error handler created when npx express-generator is used.
// 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');
});
Without that, the EJS error information (including line number, etc) gets displayed in the browser.

Cannot GET /chatroom

I am new here.
I am trying to develop a web application and I have hit a brick wall which I've been stuck on for a while now.
When running my app.js file all pages show up except for the chatroom. Could someone please take a look at the code and help me out?
I haven't included my code for register and login etc. as they are working fine. When using their router.get and .post concepts for the chatroom I just receive a "Cannot GET /chatroom" message.
Chatroom.js:
const express = require('express');
const router = express.Router();
const socketClient = require('socket.io').listen(4000).sockets;
//Chatroom page: Credit - Traversy Media - https://www.youtube.com/watch?v=hrRue5Rt6Is&t=1542s
router.get('/chatroom', (req, res) => res.render('chatroom.ejs'));
router.post('/chatroom', (req, res) => {
// Connect to Socket.io
socketClient.on('connection', function (socket) {
let chat = db.collection('UsersDB/chats');
// Create function to send status
sendStatus = function (s) {
useUnifiedTopology: true,
socket.emit('status', s);
}
// Get chats from mongo collection
chat.find().limit(100).sort({ _id: 1 }).toArray(function (err, res) {
if (err) {
throw err;
}
// Emit the messages
socket.emit('output', res);
});
// Handle input events
socket.on('input', function (data) {
let name = data.name;
let message = data.message;
// Check for name and message
if (name == '' || message == '') {
// Send error status
sendStatus('Please enter a name and message');
} else {
// Insert message
chat.insert({ name: name, message: message }, function () {
socketClient.emit('output', [data]);
// Send status object
sendStatus({
message: 'Message sent',
clear: true
});
});
}
});
// Handle clear
socket.on('clear', function (data) {
// Remove all chats from collection
chat.remove({}, function () {
// Emit cleared
socket.emit('cleared');
});
});
});
});
app.js:
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const app = express();
// Passport Config
require('./config/passport')(passport);
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
// Express body parser
app.use(express.urlencoded({ extended: true }));
// Express session
app.use(
session({
secret: 'secret',
resave: true,
saveUninitialized: true
})
);
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Routes
app.use('/', require('./routes/index.js'));
app.use('/users', require('./routes/users.js'));
app.use('/chatroom', require('./routes/chatroom.js'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
First and foremost I'd like to thank Cranky Coder; Prakher Londe; and Sunil Lulla for your replies.
I ended up figuring out how to make the chatroom show up. As mentioned before my other pages(login and register etc.) were showing up fine. Unlike the chatroom I had the backend for these in a users.js file. So what I decided to do was move my chatroom.js code into my users.js which was then called in the app.js(the file I run) with app.use('/users', require('.routes/users.js')).
I then changed my router.get code to:
router.get('/chatroom', (req, res) => res.render('chatroom', {
user: req.user
}));
Then in my router.post (see OP for context) I added a res.redirect('/users/chatroom'); before closing with the final bracket.
Lastly I of course edited my .ejs file to have
I found that doing it this way is even better because the chatroom cannot be accessed unless one is logged in.
Thank you again for all your replies and although this is a bit of a specific problem I do hope this helps someone in the future.

express jwt - Authentication Middleware Issue

I'm setting up a Token based authentication using express-jwt but the middleware which sends an error message if the token is missing or invalid is not working.
index.js file
const express = require('express');
const router = express.Router();
const {getAllUsers: findUser} = require('../controllers/users');
const {register: registerUser, login: loginUser} = require('../controllers/authentication');
const jwt = require('express-jwt');
const auth = jwt({
secret: process.env.JWT_SECRET,
userProperty: 'auth'
});
// users
router
.route('/users', auth)
.get(findUser);
// registration
router
.route('/register')
.post(registerUser);
// login
router
.route('/login',auth)
.post(loginUser);
module.exports = router;
Users Controller:
const mongoose = require('mongoose');
const User = mongoose.model('Users');
let getAllUsers = (req,res) => {
User.find((err,user)=>{
if(user){
res
.status(200)
.json({user})
}
});
};
module.exports = {
getAllUsers
};
app.js file:
require('dotenv').load();
const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const passport = require('passport');
require('./app_api/models/db');
require('./app_api/config/passport');
const index = require('./app_server/routes/index');
const apiRoutes = require('./app_api/routes/index');
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'app_server','views'));
app.set('view engine', 'ejs');
// 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(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use('/', index);
app.use('/api', apiRoutes);
//error handlers
// catch unauthorised errors
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401).send('invalid token...');
}
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
// 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;
I am setting the middleware on users route which returns a list of all users. But only authorized users should be able to access that list.
The middleware does not seem to be working as I can still get the users list even if I do not send a token.
What am I doing wrong?
Please Note: Im using POSTMAN to test this.
Update (Figured out the problem):
It was a very simple fix can't believe I didn't see it before. The issue was where I was placing auth.
I was placing it after the route url like so:
router
.route('/users', auth)
.get(findUser);
When the correct way of doing this is:
router
.route('/users')
.get(auth, findUser);
The above fixed my issue.
According to README in the repository, you should check if user property is present in the request.
The JWT authentication middleware authenticates callers using a JWT.
If the token is valid, req.user will be set with the JSON object
decoded to be used by later middleware for authorization and access
control.
Your findUser function should handle it
function findUser(req, res) {
if (!req.user) return res.sendStatus(401);
// do something else
}
You might also consider changing userProperty to requestProperty.

NodeJS :: TypeError: Cannot read property 'first_name' of undefined

I was learning the MEAN stack from a tutorial. When I tried on my localhost, I got an error.
TypeError: Cannot read property 'first_name' of undefined
at router.post (/var/www/html/mean/contactlist/routes/route.js:17:28)
I found some similar questions on the internet. But I didn't find the correct solution.
Here is my app.js file
//importing modules
var express = require('express');
var mongoose = require('mongoose');
var bodyparser = require('body-parser');
var cors = require('cors');
var path = require('path'); //core module
// calling express method
var app = express();
//connect to mongodb
mongoose.connect('mongodb://localhost/27017/contactlist');
//on connection
mongoose.connection.on('connected', () => {
console.log("connected to database database mongodb # 27017 ");
});
mongoose.connection.on('error', (err) => {
if(err){
console.log('Error in Database connection : ' + err);
}
});
//adding middleware cors
app.use(cors());
//adding body parser
app.use(bodyparser.json());
//adding static files
app.use(express.static(path.join(__dirname, 'public')));
//setting port no
const port = 3000;
//routing
var route = require('./routes/route');
//using the route
app.use('/api', route);
//testing server
app.get('/', (req, res)=>{
res.send('foobar');
});
//binding the server with port no (callback)
app.listen(port,() =>{
console.log('Server Started at Port : '+ port);
});
From a stackOverflow solution, I found,
I should use the following line before routing
app.use(bodyparser.json());
So I changed it.
And my ./routes/route.js
const express = require('express');
const router = express.Router();
const Contact = require('../models/contacts');
//Retrieving contacts
router.get('/contacts', (res, req, next) => {
contact.find(function(err,contacts){
res.json(contacts);
})
});
//Add contact
router.post('/contact', (res, req, next) => {
let newContact = new Contact({
first_name:req.body.first_name,
last_name:req.body.last_name,
phone:req.body.phone
});
newContact.save((err,contact) => {
if(err){
res.json({msg : 'Failed to add contact'});
}
else{
res.json({msg : 'Contact added successfully'});
}
});
});
//Deleting Contact
router.delete('/contact/:id', (res, req, next) => {
contact.remove({_id: req.params.id }, function(err, result){
if(err){
res.json(err);
}
else{
res.json(result);
}
});
});
module.exports = router;
Dependencies from package.json
"dependencies": {
"body-parser": "^1.17.1",
"cors": "^2.8.3",
"express": "^4.15.2",
"mongoose": "^4.9.8"
}
And the version of the nodejs is
v7.10.0
I used Postman to test the API
So I tested with POST method and following content-type option.
{"Content-Type":"application/x-www-form-urlencoded"}
This was my sample input
{
"first_name" : "RENJITH",
"last_name" : "VR",
"phone" : "1234567890"
}
Is it a version issue? Please suggest me the correct way of coding.
Your content type is {"Content-Type":"application/x-www-form-urlencoded"}
In order to support URL-encoded bodies of data you need to use this:
app.use(bodyparser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
What you used is for JSON-encoded data, such as POST: {"name":"foo","color":"red"}
EDIT:
The order of your route parameters are wrong. It's not router.post('/contact', (res, req, next)
It's actually router.post('/contact', (req, res, next)
The first parameter is the request, the second is the response.
Just Move lines body-parse at the top before route (app.js)
app.use(bodyparser.json());
app.use('/api',route);
I was facing same issue but this is how it's been solved for me
At the top of the file before any routes and after require statements use
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
then in the post request route use res.json()
here is sample code:
var express = require('express');
var bodyParser = require('body-parser')
var app = express();
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
app.get('/', (req, res) => {
res.sendFile(__dirname + './index.html')
})
app.post("/name", (req, res) => {
let fullName = req.body.first + ' ' + req.body.last;
res.json({ name: fullName })
});

Categories

Resources