module exports does not export the variable - node.js

I'm trying to creat a rest API, using the file routes.js (code bellow) but the module exports does not wotk, it does not export the const routes, if i put route it try to export, but routes makes it just dont wotk, i dont know why, this is the entire code until now
const routes = express.Router();
routes.get('/', (req, res) => {
return res.json({ message: 'test' });
});
module.exports = routes;
i tried using insominia to debug this, it work on the index file, normaly, but when i use the routes file, it just does not work (code of index bellow)
const express = require('express')
const mongoose = require('mongoose')
const routes = require('./routes')
const app = express()
mongoose.connect(**url mongoose censored**)
app.use(express.json)
app.use(routes)
app.listen(3333)
someone can help me, please

express.json is a function that returns a middleware function when you call it (allowing you to pass arguments that will be used in the middleware function). So, you need to use it like this:
app.use(express.json());
Also check if the require path is correct, you might need to provide first argument to app.use when using router
app.use('/',router)

Related

Express - can't import routes

I have a following structure,
// app.js
const express = require("express");
const app = express();
app.get("/", require("./routes/index"));
app.get("/users", require("./routes/users"));
app.listen(3000);
// /routes/index.js
const express = require("express");
const router = express.Router();
router.get("/", (req, res) => res.send("index"));
module.exports = router;
// /routes/users.js
const express = require("express");
const router = express.Router();
router.get("/login", (req, res) => res.send("login"));
router.get("/register", (req, res) => res.send("register"));
module.exports = router;
If I use app.use(...) inside app.js then the routes work correctly but I want to use app.get since I want to block any other accessible method.
Right now the index route works fine but other routes does not work.
Working sandbox: https://codesandbox.io/s/cocky-cartwright-h82d2?fontsize=14&hidenavigation=1&theme=dark
The correct way to achieve what you're trying is to utilize the 'use' function.
You said you don't want to use the app.use because you want to block any other accessible method, but utilizing the 'use' function won't allow anything that wasn't declared on your routers, so you don't need to worry about that.
What app.use does is register a middleware function to your app on the specified route. So, the code below:
app.use("/users", require("./routes/users"));
Will make that every request that match the pattern '/users' will utilize the function you provided (in this case, the router inside the users.js file).
So, if someone sends a POST request to /users/register, per example, he will get a 404, because you never created a route to handle a post on that path.
And just to make it clear why the app.get don't work the way you did, let me give a brief explanation.
When you use the app.get function, it'll be expected that the request path matches exactly the one you provided. So, when you do the following:
app.get("/users", require("./routes/users"));
The server will be expecting a request that matches /users exactly. So, something like /users/example will not trigger the callback function.
The thing is, the function to handle the request in the code above is another router:
router.get("/login", (req, res) => res.send("login"));
router.get("/register", (req, res) => res.send("register"));
So, the router will expect that the request path matches /users/login or /users/register exactly. But, if a request path matches /users/register, it will not match /users, so nothing will be called.
The reason why your '/' path works right now is because your router is expecting the same path you used on the app.js file. So, a request to '/' will match both patterns.
you can't use router.get and pass a router
router.get expect to get a method (function).
you should use app.use or use controllers like that
// /controllers/index.js
exports.renderIndex = (req, res) => {
res.send("index")
}
and in app.js
// app.js
const express = require("express");
const app = express();
const indexController = require("./controllers/index");
app.get("/", indexController.renderIndex);
app.listen(3000);

Express Router - different routes with same suffixes

I have 2 routes:
/api/system/list - list my systems
/api/system/:systemId/books/list - list books of current system
And different file for each API:
systemAPI.js:
const list = router.get('/list', Validate(Validation.list), listHandler)
return {
routes: [list]
}
bookAPI.js:
const list = router.get('/list', Validate(Validation.list), listHandler)
return {
routes: [list]
}
Finally, use the above routes:
express.use('/api/system', systemAPI.routes)
express.use('/api/system/:systemId/book', bookAPI.routes)
The problem is, when I'm entering list-books API (/api/system/:systemId/books/list), its actually calling the list-systems API (/api/system/list)
Update: Solved!
I had 2 main problems:
routes order (in app.use(..))
use different instance of Express.Router() on each API
Refer the answer below for more information.
Try reversing the order of the routes and this will probably solve your problem:
express.use('/api/system/:systemId/book', bookAPI.routes);
express.use('/api/system', systemAPI.routes);
The reason is that express evaluates routes 'greedily' and it will even resolve to partial matches. So, it is important to keep the more specific routes first before the more general ones.
Also, I think you are using the express router wrong according to the documentation the systemAPI:
const express = require('express');
const router = express.Router();
router.get('/list', Validate(Validation.list), listHandler)
module.exports = router;
The bookAPI route:
const express = require('express');
const router = express.Router();
router.get('/list', Validate(Validation.list), listHandler)
module.exports = router;
Finally import the routers and use them:
const express = require('express');
const bookRouter = require('./bookAPI'); //set the file paths based on your file structure
const systemRouter = require('./systemAPI');
const app = express();
app.use('/api/system/:systemId/book', bookRouter);
app.use('/api/system', systemRouter);

Node.js with express routing and sub routing

I am playing with node.js and I don't quite understand why something I set up is working in one instance but if I make a slight change it will not work in another instance.
in my app.js I have
app.use('/musicplayer', require('./routes/music/index'));
in my music\index.js I have
var express = require('express');
var router = express.Router();
router.use('/users', require('./users'));
module.exports = router;
in my users.js I have this - working version
var express = require('express');
var usersRouter = express.Router();
var sqllite3 = require('sqlite3').verbose();
usersRouter.get('/login', function(req, res, next) {
res.render('music/login', { title: 'Express' });
});
module.exports = usersRouter;
But I would like to encapsulate the routes I am defining into another function like this not working this just hangs the page.
Modified version of my users.js not working
var express = require('express');
var usersRouter = express.Router();
var sqllite3 = require('sqlite3').verbose();
var router = function () {
usersRouter.get('/login', function (req, res, next) {
res.render('music/login', {title: 'Express'});
});
return usersRouter;
}
module.exports = router;
In the console I can see it comes in tries the get and nevers gets routed I see this "GET /musicplayer/users/login - - ms - -".
I have even put a console.log right before the return in the anonymous function I created to know it is getting in there and that I am hooking the pathways up right from the parent routes. And I do hit that log action to the screen.
Any help or tips would be appreciated:)
PS in case you are wondering I am trying to separate out apps for different development work I want to play with. So that is why I am doing the sub routing with musicplayer/index.js instead of just putting everything in the app.js for declaring of my main routes.
Router.use() expects an instance of another Router. However your (non-working) module only returns a function.
Use this in your index.js to fix the issue:
router.use('/users', require('./users')());

How can I still use a router in node express and still have a wildcard and params?

So basically I want my code being able to go mywebsite.com/username and itll take them to their profile.
My app.js has -
var user = require('./routes/user');
app.use('/*', user);
and then in my user.js I have
router.get('/:username', function(req, res) {
console.log('the user name', req.params.username);
})
If I change router.get to just router.get('/') my console.log logs out undefined and if I leave it as router.get('/:username') I get a 404.. I also tried doing app.use('/:username', user) as well but that still didn't work.
You should't need to have a wildcard like you do on app.use
Try something like this.
Also see the express router documentation http://expressjs.com/en/guide/routing.html
// Required Moduiles
var express = require('express');
var router = express.Router();
var app = express();
// Add route to get
router.get('/:username', function(req, res) {
res.status(200).send(req.params.username)
})
// Add username
app.use('/', router)
// Start express server
app.listen(3030);
Update -
Just using app.use(router) would do the same thing if all your routes are going to be contained in this new router instance / middleware you are creating in a separate file.

How to efficiently separate routing code

Dumb/Newb question...
I am learning/working on an API in Node / Express4 and I would like to break my routes out into another module. I have it working with the following code, but it seems awkward to me to keep re-using the require('express') statement... Is there a way to move more of the code from the routes.js file into server.js and still keep my .get and .post statements in the routes module? Thanks in advance!
server.js:
'use strict';
var express = require('express');
var routes = require('./routes');
var app = express();
app.use('/api', routes);
app.listen(3000, function() {
console.log('Listening);
});
routes.js
var express = require('express'); // how do I get rid of this line?
var router = express.Router(); // can I move this to server.js?
var apiRoute = router.route('');
apiRoute.get(function (req, res) {
res.send('api GET request received');
});
module.exports = router;
Your on the right track. Its actually cool to reuse the var express = require('express'); statement each time you need it. Importing, ( requiring ), modules is a cornerstone of modular development and allows you to maintain a separation of concerns with in the files of your project.
As far as modularly adding routes is concerned: The issue is that routes.js is misleading.
In order to modularly separate out your routes you should use several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in app.js with:
var apiRoute = router.route('/api');
apiRoute.use('/<yourResource', yourResourceRouter);
For example, if you had a resource bikes:
In app.js or even a module api.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes');
apiRoute.use('/bikes', bikeRoutes);
Then in bike.js:
var express = require('express');
var router = express.Router();
var bikeRoutes = router.route('/');
bikeRoutes.get(function (req, res) {
res.send('api GET request received');
});
module.exports = bikeRoutes;
From there its easy to see that you can build many different resources and continually nest them.

Resources