Why is my express Router middleware executing multiple times? - javascript

Its my first foray into building a REST api with node/express and I have different routes based on resource type (e.g. users, auth, feed). im using express-validator in all the routes, and some of the users routes need to be protected with some extra auth middleware. But the additional middleware seems to be executing 10 times instead of once...what am I not understanding here?
app.js:
const express = require("express");
const authRoutes = require("./routes/auth");
const feedRoutes = require("./routes/feed");
const userRoutes = require("./routes/user");
var app = express();
app.use(authRoutes);
app.use(feedRoutes);
app.use(userRoutes); //userRoutes contains protected routes
app.use((error, req, res, next) => { //express built in error handler
//console.log("errorhandler: " + error);
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
const PORT = process.env.PORT || 8080;
...remaining code
routes/user.js:
//user resource related routes
const express = require("express");
//controllers and middlewares
const userController = require("../controllers/user");
const validateInputs = require("../middleware/validateInputs");
const validateAuthTokens = require("../middleware/validateAuthTokens");
//routes that use the controllers
const router = express.Router();
//protect these routes with the validateAuthToken middleware
router.get("/users/:userID/favorites", validateInputs.getFavoritesValidationRules(), validateAuthTokens, userController.getFavorites);
router.post("/users/:userID/favorites", validateInputs.addFavoriteValidationRules(), validateAuthTokens, userController.addFavorite);
//delete and add have same params and validation rules
router.delete("/users/:userID/favorites", validateInputs.addFavoriteValidationRules(), validateAuthTokens, userController.deleteFavorite);
module.exports = router;
middleware/validateAuthToken.js:
module.exports = (req, res, next) => {
console.log("inside validateAuthTokenMiddleware");
//remaining auth code
next();
}
CURRENT OUTPUT:
server now listening!
inside validateAuthTokenMiddleware 1
inside validateAuthTokenMiddleware 2
inside validateAuthTokenMiddleware 3
inside validateAuthTokenMiddleware 4
inside validateAuthTokenMiddleware 5
inside validateAuthTokenMiddleware 6
inside validateAuthTokenMiddleware 7
inside validateAuthTokenMiddleware 8
inside validateAuthTokenMiddleware 9
inside validateAuthTokenMiddleware 10
Why is the auth validation middleware executing so many times???

Related

How do I fix an express route with Stripe webhook that receives 404 and cannot GET

I have a Vue app on the frontend and a seperate express server with only a few routes. In app.js, I registered my routes as follows:
const express = require('express')
const cors = require('cors')
require('dotenv').config()
const orders = require('./routes/orders')
const webhooks = require('./routes/webhooks')
const app = express()
// http://expressjs.com/en/4x/api.html#express.urlencoded
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
// Register api routes
app.use('/', orders)
app.use('/create-payment-intent', orders)
app.use('/admin', orders)
app.use('/admin/:id', orders)
app.use('/webhook', webhooks)
/*
TODO - fall through route handler
*/
In /routes/orders.js
const express = require('express')
const router = express.Router()
const { flattenObject, orderValidationRules, validate } =
require('../middlewares/validations')
const OrdersController = require('../controllers/ordersController')
router.route('/').post(
orderValidationRules(),
validate,
OrdersController.apiPostOrder
)
router.route('/admin').get(OrdersController.apiGetOrders)
router.route('/create-payment-intent').post(OrdersController.apiCreatePaymentIntent)
router.route('/:id').delete(OrdersController.apiDeleteOrder)
module.exports = router
/routes/webhooks
const express = require('express')
const router = express.Router()
const WebhooksController = require('../controllers/webhooksController')
router.route('/webhook').post(express.raw({type: 'application/json'}),
WebhooksController.apiPostWebhookEvent)
module.exports = router
On the frontend, I can post my orders, hit admin route, the create-payment-intent route on the server is reached and responds 200, yet when I see if the webhook was reached on the stripe dashboard says pending and on the server 404 not found:
[![enter image description here][1]][1]
This is an express routing issue and I am uncertain if I in fact set my routes properly. How do I fix this? Also on the localhost port for the server I get cannot get for /create-payment-intent and for /webhook, /admin is fine.
[1]: https://i.stack.imgur.com/qoojq.png

Which part of the Router code provides the TypeError: requires Middleware function but got a Object

In this fictive project I am trying to set up the Routing structure. Although I used module.exports in both files, running a test still gives me the following error:
TypeError: Router.use() requires a middleware function but got a Object
My Code:
Minions.js
const minionsRouter = require('express').Router();
module.exports = minionsRouter;
const {
getAllFromDatabase,
addToDatabase,
getFromDatabaseById,
updateInstanceInDatabase,
deleteFromDatabasebyId,
} = require('./db.js');
minionsRouter.get('/', (req, res, next) => {
const minionsArray = getAllFromDatabase('minions');
if (minionsArray) {
res.status(200).send(minionsArray);
} else {
res.status(404).send();
}
});
API.js
const express = require('express');
const apiRouter = express.Router();
const minionsRouter = require('./minions');
const ideasRouter = require('./ideas');
const meetingsRouter = require('./meetings');
apiRouter.use('/minions', minionsRouter);
apiRouter.use('/ideas', ideasRouter);
apiRouter.use('/meetings', meetingsRouter);
module.exports = apiRouter;
Server.js
const express = require('express');
const app = express();
module.exports = app;
/* Do not change the following line! It is required for testing and allowing
* the frontend application to interact as planned with the api server
*/
const PORT = process.env.PORT || 4001;
// Add middleware for handling CORS requests from index.html
const cors = require('cors');
app.use(cors());
// Add middleware for parsing request bodies here:
const bodyParser = require('body-parser');
app.use(bodyParser.json());
// Mount your existing apiRouter below at the '/api' path.
const apiRouter = require('./server/api');
app.use('/api', apiRouter);
// This conditional is here for testing purposes:
if (!module.parent) {
// Add your code to start the server listening at PORT below:
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`)
})
};
Any help is much appreciated!

how to solve Express.js 404 status?

I'm quite new for node.js and express.js.
I'm trying to create a login form using MERN.
when I try to access register route I always jumping to 404 status I don't understand what's wrong with my code please help me on this. I'm following this youtube tutorial -- https://www.youtube.com/watch?v=y7yFXKsMD_U&t=35s
testing these codes using POSTMAN please refer below screenshot.
[![enter image description here][1]][1]
server.js | File
const express = require("express");
const morgon = require("morgan");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
require("dotenv").config({
path: "./config/config.env",
});
app.use(bodyParser.json());
if (process.env.NODE_ENV === "development") {
app.use(
cors({
origin: process.env.CLIENT_URL
})
);
app.use(morgon("dev"));
}
// Load all routes
const authRouter = require("./routers/auth.route");
// use routes
app.use("/api/", authRouter);
app.use((req, res, next) => {
res.status(404).json({
success: false,
message: "Page Not Founded",
});
});
const PORT = process.env.PORT;
app.listen(PORT, () => {
console.log(`App PORT up on port ${PORT}`);
});
config.env | File
PORT = 5000
NODE_ENV = development
CLIENT_URL = http://localhost:3000
auth.route.js | Route File
const express = require("express");
const router = express.Router();
// Load register Controller
const { registerController } = require("../controller/auth.controller.js");
// register Router path
router.post("register", registerController);
module.exports = router;
auth.controller.js | Controller File
exports.registerController = (req, res) => {
const {name, email, password} = req.body
console.log(name, email, password)
}
In your router path, you need a / in your register route.
router.post("/register", registerController);
You also do not need a trailing slash in your API route.
app.use("/api", authRouter);

get all registered route in nodejs [duplicate]

This question already has answers here:
How to get all registered routes in Express?
(31 answers)
Closed 2 years ago.
i want to return all registered route in my project.
i use this code for retur nall routes :
const app = require("express");
let routers = app._router.stack
.filter((r) => r.route)
.map((r) => {
return {
method: Object.keys(r.route.methods)[0].toUpperCase(),
path: r.route.path,
};
});
but it not worked and show me this error :
(node:13092) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'stack' of undefined
Edit :
my routes :
const express=require('express');
const router=express.Router();
const roleRouter=require('./role');
const userRouter=require('./user');
const managerRouter=require('./manager');
const accessRouter=require('./access');
const settingRouter=require('./setting');
router.use('/role',roleRouter);
router.use('/user',userRouter);
router.use('/manager',managerRouter);
router.use('/access',accessRouter);
router.use('/setting',settingRouter);
module.exports=router;
and use that in the main js file :
app.use(require("./routes/index"));
how can i return all routes in my projects ???
the app supposed to be created with express function
const express = require('express');
const app = express();
then you can get all of the registered routes, make sure to put this line after you register your app routes
console.log(app._router);
So the full code will look like this:
const express = require('express');
const app = express();
const port = 3000;
console.log(app._router); // undefined
app.get('/', (req, res) => res.send('Hello World!'))
console.log(app._router.stack); // showing routes
app.listen(port)
EDIT:
To return all of your routes from your API endpoint, you can do this (not sure why you want to do this though)
const express = require('express');
const app = express();
const port = 5000;
app.get('/', (req, res) => {
res.json(app._router.stack);
})
app.get('/example', (req, res) => {
// This route will also be listed when you call "/"
res.send();
})
app.listen(port)

Structure event listeners in Node.js [duplicate]

This question already has answers here:
How to separate routes on Node.js and Express 4?
(9 answers)
Closed 1 year ago.
In my NodeJS express application I have app.js that has a few common routes. Then in a wf.js file I would like to define a few more routes.
How can I get app.js to recognize other route handlers defined in wf.js file?
A simple require does not seem to work.
If you want to put the routes in a separate file, for example routes.js, you can create the routes.js file in this way:
module.exports = function(app){
app.get('/login', function(req, res){
res.render('login', {
title: 'Express Login'
});
});
//other routes..
}
And then you can require it from app.js passing the app object in this way:
require('./routes')(app);
Have a look at these examples: https://github.com/visionmedia/express/tree/master/examples/route-separation
In Express 4.x you can get an instance of the router object and import another file that contains more routes. You can even do this recursively so your routes import other routes allowing you to create easy-to-maintain URL paths.
For example, if I have a separate route file for my /tests endpoint already and want to add a new set of routes for /tests/automated I may want to break these /automated routes out into a another file to keep my /test file small and easy to manage. It also lets you logically group routes together by URL path which can be really convenient.
Contents of ./app.js:
var express = require('express'),
app = express();
var testRoutes = require('./routes/tests');
// Import my test routes into the path '/test'
app.use('/tests', testRoutes);
Contents of ./routes/tests.js:
var express = require('express'),
router = express.Router();
var automatedRoutes = require('./testRoutes/automated');
router
// Add a binding to handle '/tests'
.get('/', function(){
// render the /tests view
})
// Import my automated routes into the path '/tests/automated'
// This works because we're already within the '/tests' route
// so we're simply appending more routes to the '/tests' endpoint
.use('/automated', automatedRoutes);
module.exports = router;
Contents of ./routes/testRoutes/automated.js:
var express = require('express'),
router = express.Router();
router
// Add a binding for '/tests/automated/'
.get('/', function(){
// render the /tests/automated view
})
module.exports = router;
Building on #ShadowCloud 's example I was able to dynamically include all routes in a sub directory.
routes/index.js
var fs = require('fs');
module.exports = function(app){
fs.readdirSync(__dirname).forEach(function(file) {
if (file == "index.js") return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
Then placing route files in the routes directory like so:
routes/test1.js
module.exports = function(app){
app.get('/test1/', function(req, res){
//...
});
//other routes..
}
Repeating that for as many times as I needed and then finally in app.js placing
require('./routes')(app);
If you're using express-4.x with TypeScript and ES6, this would be the best template to use:
src/api/login.ts
import express, { Router, Request, Response } from "express";
const router: Router = express.Router();
// POST /user/signin
router.post('/signin', async (req: Request, res: Response) => {
try {
res.send('OK');
} catch (e) {
res.status(500).send(e.toString());
}
});
export default router;
src/app.ts
import express, { Request, Response } from "express";
import compression from "compression"; // compresses requests
import expressValidator from "express-validator";
import bodyParser from "body-parser";
import login from './api/login';
const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.get('/public/hc', (req: Request, res: Response) => {
res.send('OK');
});
app.use('/user', login);
app.listen(8080, () => {
console.log("Press CTRL-C to stop\n");
});
Much cleaner than using var and module.exports.
Full recursive routing of all .js files inside /routes folder, put this in app.js.
// Initialize ALL routes including subfolders
var fs = require('fs');
var path = require('path');
function recursiveRoutes(folderName) {
fs.readdirSync(folderName).forEach(function(file) {
var fullName = path.join(folderName, file);
var stat = fs.lstatSync(fullName);
if (stat.isDirectory()) {
recursiveRoutes(fullName);
} else if (file.toLowerCase().indexOf('.js')) {
require('./' + fullName)(app);
console.log("require('" + fullName + "')");
}
});
}
recursiveRoutes('routes'); // Initialize it
in /routes you put whatevername.js and initialize your routes like this:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index', { title: 'index' });
});
app.get('/contactus', function(req, res) {
res.render('contactus', { title: 'contactus' });
});
}
And build yet more on the previous answer, this version of routes/index.js will ignore any files not ending in .js (and itself)
var fs = require('fs');
module.exports = function(app) {
fs.readdirSync(__dirname).forEach(function(file) {
if (file === "index.js" || file.substr(file.lastIndexOf('.') + 1) !== 'js')
return;
var name = file.substr(0, file.indexOf('.'));
require('./' + name)(app);
});
}
I am trying to update this answer with "express": "^4.16.3". This answer is similar to the one from ShortRound1911.
server.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const db = require('./src/config/db');
const routes = require('./src/routes');
const port = 3001;
const app = new express();
//...use body-parser
app.use(bodyParser.urlencoded({ extended: true }));
//...fire connection
mongoose.connect(db.url, (err, database) => {
if (err) return console.log(err);
//...fire the routes
app.use('/', routes);
app.listen(port, () => {
console.log('we are live on ' + port);
});
});
/src/routes/index.js:
const express = require('express');
const app = express();
const siswaRoute = require('./siswa_route');
app.get('/', (req, res) => {
res.json({item: 'Welcome ini separated page...'});
})
.use('/siswa', siswaRoute);
module.exports = app;
/src/routes/siswa_route.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({item: 'Siswa page...'});
});
module.exports = app;
If you want a separate .js file to better organize your routes, just create a variable in the app.js file pointing to its location in the filesystem:
var wf = require(./routes/wf);
then,
app.get('/wf', wf.foo );
where .foo is some function declared in your wf.js file. e.g
// wf.js file
exports.foo = function(req,res){
console.log(` request object is ${req}, response object is ${res} `);
}
One tweak to all of these answers:
var routes = fs.readdirSync('routes')
.filter(function(v){
return (/.js$/).test(v);
});
Just use a regex to filter via testing each file in the array. It is not recursive, but it will filter out folders that don't end in .js
I know this is an old question, but I was trying to figure out something like for myself and this is the place I ended up on, so I wanted to put my solution to a similar problem in case someone else has the same issues I'm having. There's a nice node module out there called consign that does a lot of the file system stuff that is seen here for you (ie - no readdirSync stuff). For example:
I have a restful API application I'm trying to build and I want to put all of the requests that go to '/api/*' to be authenticated and I want to store all of my routes that go in api into their own directory (let's just call it 'api'). In the main part of the app:
app.use('/api', [authenticationMiddlewareFunction], require('./routes/api'));
Inside of the routes directory, I have a directory called "api" and a file called api.js. In api.js, I simply have:
var express = require('express');
var router = express.Router();
var consign = require('consign');
// get all routes inside the api directory and attach them to the api router
// all of these routes should be behind authorization
consign({cwd: 'routes'})
.include('api')
.into(router);
module.exports = router;
Everything worked as expected. Hope this helps someone.
index.js
const express = require("express");
const app = express();
const http = require('http');
const server = http.createServer(app).listen(3000);
const router = (global.router = (express.Router()));
app.use('/books', require('./routes/books'))
app.use('/users', require('./routes/users'))
app.use(router);
routes/users.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'John Smith'})
}
module.exports = router
routes/books.js
const router = global.router
router.get('/', (req, res) => {
res.jsonp({name: 'Dreams from My Father by Barack Obama'})
}
module.exports = router
if you have your server running local (http://localhost:3000) then
// Users
curl --request GET 'localhost:3000/users' => {name: 'John Smith'}
// Books
curl --request GET 'localhost:3000/books' => {name: 'Dreams from My Father by Barack Obama'}
I wrote a small plugin for doing this! got sick of writing the same code over and over.
https://www.npmjs.com/package/js-file-req
Hope it helps.
you can put all route functions in other files(modules) , and link it to the main server file.
in the main express file, add a function that will link the module to the server:
function link_routes(app, route_collection){
route_collection['get'].forEach(route => app.get(route.path, route.func));
route_collection['post'].forEach(route => app.post(route.path, route.func));
route_collection['delete'].forEach(route => app.delete(route.path, route.func));
route_collection['put'].forEach(route => app.put(route.path, route.func));
}
and call that function for each route model:
link_routes(app, require('./login.js'))
in the module files(for example - login.js file), define the functions as usual:
const login_screen = (req, res) => {
res.sendFile(`${__dirname}/pages/login.html`);
};
const forgot_password = (req, res) => {
console.log('we will reset the password here')
}
and export it with the request method as a key and the value is an array of objects, each with path and function keys.
module.exports = {
get: [{path:'/',func:login_screen}, {...} ],
post: [{path:'/login:forgotPassword', func:forgot_password}]
};

Categories

Resources