How to debug EJS - javascript

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.

Related

'app.use() requires a middleware function'

I was making a registration and Login page for user in Node using express. When i try to run my app.js file it gives this "app.use()" error. Below is my app.js code
const express= require("express");
const app= express();
const path= require("path");
const hbs= require("hbs");
var session= require("express-session");
const { urlencoded } = require("express");
const port= process.env.PORT || 3000;
require("dotenv").config;
const static_path= (path.join(__dirname,"../public"));
const template_path= (path.join(__dirname,"../templates/views"));
const partials_path= (path.join(__dirname,"../templates/partials"));
const db= require("./db/db.js");
const cookieParser= require("cookie-parser");
const e = require("express");
hbs.registerPartials(partials_path);
var regisRouter= require("../src/routes/regis");
var loginRouter= require("../src/routes/login");
var dashbRouter= require("../src/routes/dashboard");
var logoutRouter= require("../src/routes/logout");
app.use('/regis',regisRouter);
app.use('/login',loginRouter);
app.use('/dashboard',dashbRouter);
app.use('/logout',logoutRouter);
// 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');
});
app.use(express.static(static_path));
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use("cookieParser()");
app.set("view engine", "hbs");
app.set("views",template_path);
const oneDay = 1000 * 60 * 60 * 24;
app.use(session({
secret: "secret123",
resave: false,
saveUninitialized: true,
cookie: {maxAge: oneDay}
}));
app.get("/",(req,res) =>{
session= req.session;
if(session.id)
{
res.send("Welcome User <a href=\'/logout'>click to logout</a>");
}
else
res.render("index");
});
// app.post("/register", async(req,res) =>{
// try {
// const password= req.body.password;
// const cpassword= req.body.confirmpassword;
// if(password===cpassword)
// {
// }
// else
// {
// res.send("invalid login credentials");
// }
// } catch (error) {
// res.status(400).send(error);
// }
// });
app.listen(port,() =>{
console.log(`this is port no. ${port}`);
});
I think probably this part has an error, but i am not so sure about it
app.use('/regis',regisRouter);
app.use('/login',loginRouter);
app.use('/dashboard',dashbRouter);
app.use('/logout',logoutRouter);
Below is the folder structure if it is of any help
I am not able to understand this error. If someone could tell me it would be of great help , thankyou!
The problem is you have to pass a function as a parameter to app.use(), but you are giving a string into it "cookieParser()".
Change
app.use("cookieParser()");
To
app.use(cookieParser());

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.

Node.JS and Postgres Search Bar

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.

Express Route 404

I'm having trouble with my node.js express routes. I'm really new to it and I can't see my mistake. I'm always getting a 404 Error when requesting localhost:2700/api/subs, but I think that my route is correct, isn't it? Can anybody see a mistake?
Beginning of the Error Message:
Error: Not Found
at ****/app.js:45:13
at Layer.handle [as handle_request] (****/node_modules/express/lib/router/layer.js:95:5)
Here is the 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');
const mongoose = require('mongoose');
// establish connection to the Database
mongoose.connect('mongodb://localhost/test', {
useMongoClient: true
});
mongoose.connection.once('open', function() {
console.log('Connection to Database has been established..');
}).on('error', function(error){
console.log(error);
});
var index = require('./routes/index');
var users = require('./routes/users');
Subscriber = require('./routes/subscriber.js');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// 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('/', index);
app.use('/users', users);
// 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 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');
});
app.get('/api/subs', function(req, res){
Subscriber.getSubscribers(function(err, subscribers){
if(err){
throw err;
}
res.json(subscribers);
});
});
// ... here is a function which creates the database objects and saves
// them. took it out for better overview....
app.listen(2700, function(){
console.log("Listening on Port 2700")
});
module.exports = app;
and the subscriber.js which is in the subdirectory ./routes:
const mongoose = require('mongoose');
var subscriberSchema = mongoose.Schema({
//seqnr shall go here. dunno how to declare integer x)
nr: Number,
name: String,
email: String,
uLink: String,
anwalt: String
});
var Subscriber = module.exports = mongoose.model('Subscriber', subscriberSchema);
//get Subscriber
module.exports.getSubscribers = function(callback, limit){
Subscriber.find(callback).limit(limit);
};
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
You need to put your 404 app.use after all the other uses, otherwise it will ignore the api/subs after it.
Also, this bit will never run, because it also comes after an api.use that will always throw an error:
// 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');
});
Plus, you really shouldn't be throwing errors for 404s. It should tell the end user the page doesn't exist, but it shouldn't crash your script.
Also I agree with the other answer that says you should move those code blocks into separate router files, but that's more for good practice and structuring than for this particular bug.
Try putting it in a separate file and including it where you do with other routes, before the 404 handler
app.use('/', index);
app.use('/users', users);
So... make a subs.js route
var express = require('express');
var router = express.Router();
Subscriber = require('./routes/subscriber.js');
router.get('/', function(req, res){
Subscriber.getSubscribers(function(err, subscribers){
if(err){
throw err;
}
res.json(subscribers);
});
});
module.exports = router;
Then include it in your app.js
var subs= require('./routes/subs');
...
api.use('/api/subs', subs);
...
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

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.

Categories

Resources