Express Middleware Issue - node.js

On routes/index.js it works fine if I leave the module.exports = routes;
But If I change it to the following to allow multiple files then I get a middleware error:
module.exports = {
routes
};
var app = express();
const routes = require('./routes');
const port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use('/', routes);
app.get('/', (req, res) => {
res.send('Please visit: http://domain.com');
}, (err) => {
res.send(err);
});
//routes/index.js
const routes = require('./MainRoutes');
module.exports = routes;
//routes/Main Routes.js
const routes = require('express').Router();
routes.post('/main', (res, req) => {
//code here works
});
module.exports = routes;
The error is: Router.use() requires middleware function but got a ' + gettype(fn));

MainRoutes.js exports the express router object, which middleware will understand just fine if you do
module.exports = routes; // routes/index.js
However, when you do
module.exports = {
routes
};
You are now nesting that router object in another object, which middleware can't understand.
In your main server file you can do
const {routes} = require('./routes');
to get the router object properly.

Modify the routes/index.js as:
const routes = require('express').Router();
routes.use('/main', require('./MainRoutes'));
// Put other route paths here
// eg. routes.use('/other', require('./OtherRoutes'))
module.exports = routes;
Modify the Main Routes.js as:
const routes = require('express').Router();
routes.post('/', (res, req) => {
// route controller code here
});
module.exports = routes;
Hope this helps you.

Related

I cannot get /users json

I'm new to express and node js, I recently learned how to write API for express but at the end, I get some sort of problem which not resolved by me after several tries. I could not get a response on localhost:8080/users
src/routes/users.js
const { Router } = require("express");
const router = Router();
const getUsers = (req, res) =>
res.send(Object.values(req.context.models.users));
const getUser = (req, res) =>
res.send(req.context.models.users[req.params.userId]);
router.get("/users/", getUsers);
router.get("/users/:userId", getUser);
module.exports = router;
src/routes/index.js
const user = require("./user");
const message = require("./message");
module.exports = {
user,
message
};
src/index.js
const express = require("express");
const app = express();
// Custom Modules
const routes = require("./routes");
const models = require("./models");
// Application-Level Middleware Starts
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((req, res, next) => {
req.context = {
models,
me: models.users[1]
};
console.log(req.context.models.users);
next();
});
// Used Routes
app.use("/users", routes.user);
app.use("/messages", routes.message);
// App Listning to HTTPS Module
app.listen(process.env.PORT);
You need to fix your endpoints in users.js:
router.get("/", getUsers);
router.get("/:userId", getUser);
The reason is because of app.use("/users", routes.user); in your index.js, where the endpoint for users is set. If you leave /users/ in users.js it would be localhost:8080/users/users/. Same problem might be with /messages.

How can I separate route files?

I have a route file in my project and it is called from my app with these lines:
var index = require('./routes/index');
app.use('/', index);
But I need to separate the route file, and I'm trying to do this:
var index = require('./routes/index');
var user = require('./routes/user');
app.use('/', index);
app.use('/user', user);
In route user.js I put the service that I need to access from the client. But it's not working. I don't know what is wrong, I am a beginner in Node.js.
The request returns:
GET /user/find 304 4.203 ms - -
And user.js file is:
var router = express.Router();
router.get('/user/find',function(req, res){
Object.find(function(err, s){
if(err) res.send(err);
res.json(s);
});
});
module.exports = router;
*This request works well on index.js
You put user router under /user route, and in your user router you defined app.get('/user/find'), so the actual path would be /user/user/find, you need to remove the user prefix in router
var router = express.Router();
router.get('/find',function(req, res){
Object.find(function(err, s){
if(err) res.send(err);
res.json(s);
});
});
module.exports = router;
A simple way to do this can be:
index.js
var express = require('express')
var app = express()
var route1 = require('./route1')
var route2 = require('./route2')
app.use('/', route1);
app.use('/hello', route2);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
route1.js
var express = require('express')
var router = express.Router()
router.get('/', function (req, res) {
res.send('Hello route1');
})
module.exports = router
route2.js
var express = require('express')
var router = express.Router()
router.get('/', function (req, res) {
res.send('Hello route2');
})
module.exports = router
Have you made sure to include a module.exports = router at the end of each of your route files?
Your route files should be set up thusly:
var router = require('express').Router();
router.get("/example", function (req, res) {
res.send("Hello");
});
module.exports = router;

ERROR app.use() requires middleware functions: (so how to set router for app.use in express node.js)?

basically im just trying to seprate routes, models, and controller in node.js application.
i have following files to setup very very basic node.js application.
controller/cv.js
module.exports = {
get: function(req, res, next){
console.log("GET REQUESTS")
next();
}
}
routes/cv.js
var express = require('express');
var CvRouter = express.Router();
var CvController = require('../controller/cv')
CvRouter.get('/', function(req, res, next){
console.log("GET REQUESTS")
next();
})
module.export = CvRouter
app.js
const express = require('express');
const bodyParser= require('body-parser')
var path = require('path')
const app = express();
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
var router = express.Router();
require('./router')(app)
app.listen(3000, function() {
console.log('listening on 3000')
})
router.js
var CvRouter = require('./routes/cv')
module.exports = function(app) {
app.use([CvRouter]);
};
Basicaly this last file router.js is generting error when i use app.use([CvRouter])
ERROR is: throw new TypeError('app.use() requires middleware functions');
how i can resolve it? i also know its returning object of router. and app.use expecting function in parameter. but how i can achieve my desired MVC pattern of node.js?
as said in comment - you have a typo.
The file routes/cv.js contains module.export instead of module.exports, that makes CvRouter undefined.
Kill the array literal
var CvRouter = require('./routes/cv')
module.exports = function(app) {
app.use(CvRouter);
};

Multiple module.exports

I have this code here
var router = require('./Router/index')(app, passport);
Im passing app and passport to my index.js file
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute'));
// Website
app.use('/', require('./Routes/Website'));
app.use('/keys', require('./Routes/KeysRoute'));
app.use('/users', require('./Routes/UsersRoute'));
};
Im going to use passport in my website route file
var express = require('express');
var router = express.Router();
var Users = require('../../Class/Users');
router.get('/CreateUser', function (req, res) {
Users.getUsers(function(result){
res.render('NewUser');
});
});
module.exports = router;
How can i pass the passport object over to be used in my website route file?
You can use the pattern further of exporting a function. Though, instead of exporting the router, the function can return it.
var express = require('express');
var Users = require('../../Class/Users');
module.exports = function (passport) {
var router = express.Router();
// ...
return router;
};
Then, invoking the exported function to pass along passport from index.js:
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute')(passport));
// ...
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute'));
// Website
app.use('/', require('./Routes/Website')(passport));
app.use('/keys', require('./Routes/KeysRoute'));
app.use('/users', require('./Routes/UsersRoute'));
};
You Website route file
var express = require('express');
var router = express.Router();
var Users = require('../../Class/Users');
module.exports = function (passport) {
router.get('/CreateUser', function (req, res) {
Users.getUsers(function(result){
res.render('NewUser');
});
});
}

How to separate routes on Node.js and Express 4?

I want to separate Routes from my server.js file.
I am following this tutorial on Scotch.io
http://scotch.io/tutorials/javascript/build-a-restful-api-using-node-and-express-4
It is working if all lines are on server.js file. But I am failing to separate. How can I make this work?
server.js
// set up ======================================================================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// configuration ===============================================================
app.use(bodyParser());
var port = process.env.PORT || 8000;
var mongoose = require('mongoose');
var database = require('./config/database');
mongoose.connect(database.url);
var Video = require('./app/models/video');
// routes =======================================================================
app.use('/api', require('./app/routes/routes').router);
// listen (start app with node server.js) ======================================
app.listen(port);
console.log("ready captain, on deck" + port);
module.exports = app;
And the app/routes/routes.js
var express = require('express');
var router = express.Router();
router.use(function(req, res, next) {
console.log('Something is happening.');
next();
});
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our rest video api!' });
});
router.route('/videos')
.post(function(req, res) {
var video = new Video();
video.title = req.body.title;
video.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Video criado!' });
});
})
.get(function(req, res) {
Video.find(function(err, videos) {
if (err)
res.send(err);
res.json(videos);
});
});
module.exports.router = router;
Server.js
var express = require('express');
var app = express();
app.use(express.static('public'));
//Routes
app.use(require('./routes')); //http://127.0.0.1:8000/ http://127.0.0.1:8000/about
//app.use("/user",require('./routes')); //http://127.0.0.1:8000/user http://127.0.0.1:8000/user/about
var server = app.listen(8000, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
routes.js
var express = require('express');
var router = express.Router();
//Middle ware that is specific to this router
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
// Define the home page route
router.get('/', function(req, res) {
res.send('home page');
});
// Define the about route
router.get('/about', function(req, res) {
res.send('About us');
});
module.exports = router;
*In routs.js you should define Middle ware
ref http://wiki.workassis.com/nodejs-express-separate-routes/
As far as separating routes from main file is concerned..
Server.js
//include the routes file
var routes = require('./routes/route');
var users = require('./routes/users');
var someapi = require('./routes/1/someapi');
////////
app.use('/', routes);
app.use('/users', users);
app.use('/1/someapi', someapi);
routes/route.js
//last line - try this
module.exports = router;
Also for new project you can try on command line
express project_name
You will need express-generator for that
Another way to separate routes into their own files with Express 4.0:
server.js
var routes = require('./routes/routes');
app.use('/', routes);
routes.js
module.exports = (function() {
'use strict';
var router = require('express').Router();
router.get('/', function(req, res) {
res.json({'foo':'bar'});
});
return router;
})();
One way to separate routes into their own file.
SERVER.JS
var routes = require('./app/routes/routes'); //module you want to include
var app=express();
routes(app); //routes shall use Express
ROUTES.JS
module.exports=function(app) {
//place your routes in here..
app.post('/api/..., function(req, res) {.....} //example
}
If you're using express-4.x with TypeScript and ES6, this would be a 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 clear and reliable rather using var and module.exports.
We Ought To Only Need 2 Lines of Code
TL;DR
$ npm install express-routemagic --save
const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')
That's it!
More info:
How you would do this? Let's start with file structuring:
project_folder
|--- routes
| |--- api
| |--- videos
| | |--- index.js
| |
| |--- index.js
|
|--- server.js
Note that under routes there is a structure. Route Magic is folder aware, and will imply this to be the api uri structure for you automatically.
In server.js
Just 2 lines of code:
const magic = require('express-routemagic')
magic.use(app, __dirname, 'routes')
In routes/api/index.js
const router = require('express').Router()
router.get('/', (req, res) => {
res.json({ message: 'hooray! welcome to our rest video api!' })
})
In routes/api/videos/index.js
Route Magic is aware of your folder structure and sets up the same structuring for your api, so this url will be api/videos
const router = require('express').Router()
router.post('/', (req, res) => { /* post the video */ })
router.get('/', (req, res) => { /* get the video */ })
Disclaimer: I wrote the package. But really it's long-overdue, it reached my limit to wait for someone to write it.
An issue I was running into was attempting to log the path with the methods when using router.use ended up using this method to resolve it. Allows you to keep path to a lower router level at the higher level.
routes.js
var express = require('express');
var router = express.Router();
var posts = require('./posts');
router.use(posts('/posts'));
module.exports = router;
posts.js
var express = require('express');
var router = express.Router();
let routeBuilder = path => {
router.get(`${path}`, (req, res) => {
res.send(`${path} is the path to posts`);
});
return router
}
module.exports = routeBuilder;
If you log the router stack you can actually see the paths and methods
I simply delcared the files and used require in the server.js file
app.use(express.json());
require('./app/routes/devotion.route')(app);
require('./app/routes/user.route')(app);
In my case, I like to have as much Typescript as possible. Here is how I organized my routes with classes:
export default class AuthService {
constructor() {
}
public login(): RequestHandler {
return this.loginUserFunc;
}
private loginUserFunc(req: Request, res: Response): void {
User.findOne({ email: req.body.email }, (err: any, user: IUser) => {
if (err)
throw err;
if(!user)
return res.status(403).send(AuthService.noSuccessObject());
else
return AuthService.comparePassword(user, req, res);
})
}
}
From your server.js or where you have your server code, you can call the AuthService in the following way:
import * as express from "express";
import AuthService from "./backend/services/AuthService";
export default class ServerApp {
private authService: AuthService;
this.authService = new AuthService();
this.myExpressServer.post("/api/login", this.authService.login(), (req: express.Request, res: express.Response) => {
});
}

Resources