Where is the domain mapped to app routers? - node.js

const express = require('express');
const router = express.Router();
router.get('/specialRoute', function (req, res, next) {
// route is now http://domain:3000/route/specialRoute
});
router.get('/', function (req, res, next) {
// route is now http://domain:3000
});
module.exports = router;
However, where is the 'domain' mapped to '/' ? In other words, where is the logic to route 'http://domain:3000' -> router.get('/',

An express.Router is not an express application (which is what is used for said binding).
Usually the mapping defaults to localhost because you assign a domain name to an IP and the DNS does the wiring.
If you look at Express's listen documentation on devdocs you'd see that you can pass a host as a second parameter : app.listen(80, "mywebsite");

If you want to map a router to the root ("the domain") you first need an express application:
const app = express();
Then, use the router:
app.use(router);
To make it even neater: Express apps themselves are instances of Router so if you replace router.get with app.get it will be functionally the same.
The reason you would want to create a new Router and export it would be to have multiple router modules and then require them from a main file like this:
const express = require("express");
const app = express();
app.use("/shop", require("./path-to-your-shop-router.js"));
Also, don't forget to make the server listen so you can visit it on your computer:
// Ports <1024 are usually restricted
app.listen(3000);

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);

Difference between app.use('/', router) and app.use(router)

I am working on a node.js application and saw that some people use
app.use('/',router)
and some people use
app.use(router)
What is the difference between these two and which one should I use?
There's no difference in this case.
app.use([path,] callback [, callback...])
If you call app.use without specifying path explicitly, it takes a default value which is /.
But using this paramaeter you can have more than a single router in your app. See examples in the documentation:
var express = require('express');
var app = express(); // the main app
var admin = express(); // the sub app
admin.get('/', function (req, res) {
console.log(admin.mountpath); // /admin
res.send('Admin Homepage');
});
app.use('/admin', admin); // mount the sub app

Difference between app.get() or router.get() - ExpressJs

What is the difference between:
var express = new express();
var app = new express();
app.get("/", function() {
.....
})
And:
var express = new express();
var router= express.Router();
router.get("/", function() {
.....
})
app.get can be used to create routes for your application at the top level.
From the documentation about express.Router
Use the express.Router class to create modular, mountable route handlers. A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.
A router needs to be mounted to an app:
const router = express.Router();
router.get("/", (res, req) => res.end());
router.post("/", (res, req) => res.end());
app.use("/empty", router);
This allows you to more easily encapsulate the functionality of several routes into an app which will be namespaced under a particular route.
When express() is called in app.js, an app object is returned. Think of an app object as an Express application.
When express.Router() is called, a slightly different "mini app" is
returned. The idea behind the "mini app" is that different routes in
your app can become quite complicated, and you'd benefit from moving
that logic into a separate file.
Check this SO Thread for details.

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.

Creating a Modular REST API in ExpressJS

I'm having some trouble creating a RESTful API in Node/Express. In the app I'm building, a user has many messages, and messages belong to users. I need to be able to make an HTTP requests to retrieve all messages by a particular user. Here's the basic structure of the app, starting with the basic server, which delegates routing to a file called 'config/middleware.js'.
//server.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
require('./config/middleware.js')(app, express);
var port = process.env.PORT || 8080;
app.use(bodyParser.json());
app.use(express.static(__dirname + '/../client'));
app.listen(port);
This is the middleware file where we send requests to the appropriate router. A request made to 'users/5/messages' would get routed to the messages router, and a request made to 'users/5' would get routed to the users router.
// config/middleware.js
module.exports = function(app, express) {
var usersRouter = express.Router();
var messagesRouter = express.Router();
app.use('/users/:userId/messages', messagesRouter);
app.use('/users', usersRouter);
require('../routers/users')(usersRouter);
require('../routers/messages')(messagesRouter);
};
This is the messages router. If a get request is made to '/users/5/messages', I want the getAllMessages function to be run, which should return all messages by the user with userId 5.
// routers/messages.js
var messagesController = require('../controllers/messages');
module.exports = function(app) {
app.get('/:messageId', messagesController.getMessage);
app.get('/', messagesController.getAllMessages);
};
The problem is that the getAllMessages function doesn't have access to the 'userId' parameter (with value of 5), which is required in order to make an appropriate query to the database. The getAllMessages function in the controller expects the userId to be stored on req.params.userId. Is there any way to get the userId of 5 to be present on the req.params object inside the getAllMessages function?
The req.params are not passed down the route chain. To do so, you could do something like
In server.js, create a key on req. This will pass on your data between routes. Do this before mounting the routes.
app.use(function (req, res, next) {
req._data = {};
next();
});
In config/middleware.js,
module.exports = function(app, express) {
var usersRouter = express.Router();
var messagesRouter = express.Router();
// attach usedId
app.use('/users/:userId/messages', function (req, res, next) {
req._data.userId = req.params.userId;
next();
});
// mount the router
app.use('/users/:userId/messages', messagesRouter);
app.use('/users', usersRouter);
require('../routers/users')(usersRouter);
require('../routers/messages')(messagesRouter);
};
This way, you would have access to req._data.userId in routers/messages.js.
Side note: A better way to structure the routes would be to use something like, (read shameless plug), https://github.com/swarajgiri/express-bootstrap/blob/master/web/routes.js
You can use app.locals or res.locals to pass some datas.
There is a good explanation about locals.
An usage sample:
app.locals.userid = req.params.userId; //binding userid
app.locals.userid // => '5'
OR: put a global variable.
user_id_tmp = req.params.userId;
Now this is become global variable in app. So you can call user_id_tmp variable from anywhere.
I was looking for same.
Here is modules app example on github and auther site
Also we can change or update structure base on our requirements

Resources