NodeJS Express routes in external file 404 Not Found - node.js

I'm new to NodeJs and express. My goal is to have a separate route file that contains all my application routes. So I created a file called routes.js. The content looks like this:
const express = require('express');
const router = express.Router();
router.get('auth/register', require('./controllers/auth/register'));
module.exports = router;
In my main file, I require the file with this line. The app variable contains my express instance.
app.use('/', require('./routes'));
If I call http://localhost/auth/register in my browser, I'm always running into a 404 Not Found error. When I define the route directly in the main file with app.get('/auth/register', require('./controllers/auth/register')); it works well. There are no errors in my console.
Has anyone an idea why my sperate route file does not work? Thank you for your help!

Traditionally, I do the following which is to pass the express instance into your routes module:
once I have instantiated my express instance called app
app.js
require('./routes.js')(app);
routes.js where registerUser us the function to call when the route is matched
module.exports = (app) => {
app.route('/auth/register')
.post(registerUser);
}

You want to pass app into your routes file. A good pattern for this is to import your routes in your main file, like const routes = require('./routes');
In routes, you can define all of your routes like so:
module.exports = (app, router) => {
router.route("/").get()
router.route("/something_else").post()
app.use("/api", router)
...
};
This way, in your main file, you can do: routes(app, router) and have access to app and router inside your routes.js.

Related

Routes are not working in my express js app

I was working on a personal express project. I've created two files one server file and other restaurants.route.js to sepearate routes and server code. But I'm not able trigger the home route from local host. Moreover no console error is showing only the 404 page error.
server.js code:
import express from "express";
import cors from "cors";
import restaurants from "./api/restaurants.route.js";
// initialising express app
const app = express();
// applying middlewears
app.use(cors());
app.use(express.json());
app.use("api/v1/restaurants", restaurants);
app.use("*", (req, res) => res.status(404).json({error: "not found"}));
export default app;
restaurants.route.js:
import express from "express";
// express router
const router = express.Router();
router.route("/")
.get((req, res) => {
res.send("Hello World");
});`enter code here`
export default router;
It looks like you might be missing the leading forward slash (/) in the path you're using to mount the restaurants router in your server.js file. When you use the app.use() method to mount a router, the path you specify should start with a forward slash.
So instead of this:
app.use("api/v1/restaurants", restaurants);
Try this:
app.use("/api/v1/restaurants", restaurants);

Confusion with app.use with Router() in express

I was learning Express in Node.js and came across Router() allowing us to modularize our routes. But than I found this code:
// we'll create our routes here
// get an instance of router
var router = express.Router();
...
// route with parameters (http://localhost:8080/hello/:name)
router.get('/hello/:name', function(req, res) {
res.send('hello ' + req.params.name + '!');
});
// apply the routes to our application
app.use('/', router);
What confused me is that why we need to use app.use('/', router); to apply the routes. That is, what if we use app.get('/', router);
I am giving you a simple code example to make you understand the use of express.Router(). Yes you are right that it helps in modularization. Actually it makes our main app.js file clean from all the routes. We just put all those routes based on their purposes in different files and require them when needed.
so suppose I have two files app.js and register.js
// app.js file's code goes here
let express = require("express")
let app = express()
let register = require("./routes/register")
app.use(register) // This will tell your app to import all those routes which are in register
// register.js file's code goes here
let express = require("express")
let router = express.Router()
router.get("/register", callback_function);
router.post("/register", callback_function);
module.exports = router;
So basically what I am trying to show is your register.js can contain all types of HTTP requests(GET, POST, PUT,...) and when we use app.use(register) this will handle all those routes. app.get("route_path", callback_function) is only for handling get requests to that path.
Router is just a middleware of it's own. If you use app.get('/', router) you will use the router just for GET requests. Using use channels all requests there.
When app.use is used then it handled all the HTTP methods, but when app.get is used it takes just GET method.
Added advantage to app.use is that route will match any path that follows its path immediately with a /.
For example:
app.use('/v1', ...)
will match /users, /users/accounts, /users/accounts/account-id, and so on.

Is it possible to have different route files in Express (NodeJS) app?

I'm a NodeJS beginner and I'm using express. My directory is like this :
__app
|_assets
|_controllers
|_somemodel.controller.js
|_models
|_somemodel.model.js
|_user.model.js
|_routes
|_route.js
|_passport.routes.js
|_somemodel.routes.js
|_views
|_note
|_index.ejs
|_passport
|_index.ejs
|_login.ejs
|_profile.ejs
...
__config
|_database.config.js
|_passport.config.js
__node_modules
package.json
server.js
the thing I wanna know is that is it possible to have a general routes file and then include or require other route files in that ? Like my route.js ?
And is this directory correct while using Express and Passport as authentication?
yes, you can require other route files into a common file like bellow.
somemodel.contoller.js
module.exports.someMethod = (req, res) => {
// do something
}
somemodel.routes.js
const controller = require("path-to-somemodel-controller")
module.exports = (app) {
app.route("/somepath")
.get(controller.someMethod)
// other methods
}
route.js
// you need to parse the app into route module
module.exports = (app) => {
require('somemodel.routes')(app);
// others goes here
}
server.js
const app = express();
require('path-to-route.js')(app
)

How to set routes in Express? app.use() vs app.get()

I have site stub, where routing is set in 2 places.
First in app.js:
...
var index = require('./routes/index');
var users = require('./routes/users');
...
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
...
something is set with use. Next inside referred scripts, like index.js:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var path = require('path');
var config = require('../config');
/* GET home page. */
router.get('/', function(req, res) {
var data = {};
...
Suppose I wish to use infromation from Express Routing doc. Where I should put the routing for, say, /users/:userId/books/:bookId?
In docs, get is called against app, while in my stub, get is called against router and in two-step manner.
Where to hook?
In docs get is called against app because they set their endpoints in app.js file. In your index.js you return the router from the file with module.exports = router;, which is app's router. Now in your app.js file says
app.use('/', index);
app.use('/users', users);
These are the routes. You are saying that all the endpoints which are in index file are starting with / and the endpoints which are in users file are starting with /users.
So the route /users/:userId/books/:bookId must be in users.js file like this
router.get('/:userId/books/:bookId', function(req, res, next) {
// do something
});
If you want to handler this route - /users/:userId/books/:bookId, then you need to write following handler in your routes/users.js file.
router.get('/:userId/books/:bookId', function(req, res) {
var data = {};
});//get route
Basically, in app.js you are categorising url's based on its first part e.g. users. So, all your routes that start with /users will be handled by your routes/users.js class. All other routes will be handled by routes/index.js, because that is defined to handle / (there is no /users, /admin etc. so all routes that are not handled by users.js can be handled in this.)
Also, in these route handler files, you define a router object, add all route handlers to it and export it at the bottom. So when you are in these files, you need to use router and in app.js you can directly use app.get() etc.

Express: how can I get the app from the router?

I know I can get the Express app from inside an individual route with:
req.app
However I need to start a single instance of a module inside routes/index.js, i.e.:
var myModule = require('my-module')(propertyOfApp)
How can I get the express app from the router?
It really depends on your own implementation, but what I suggested in the comments should be working:
// index.js
module.exports = function(app) {
// can use app here
// somehow create your router and do the magic, configure it as you wish
router.get('/path', function (req, res, next) {});
return router;
}
// app.js
// actually call the function that is returned by require,
// and when executed, the function will return your configured router
app.use(require('./index')(app));
p.s.
Of course this is just a sample - you can configure your router with path, and all kind of properties you wish. Cheers! :)

Resources