Pardon me for this stupid question, but can someone explain me how the cors middleware work?
I accidentally called an auth middleware by adding brackets after it and it ran that middleware without even me requesting to that route.
I know that adding brackets after function invokes it but what is it with cors middleware that we add those brackets after it??
usage of cors middleware from docs:
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
using auth middleware with () gives error:
app.get('/products/:id', auth(), function (req, res, next) {
res.json({msg: 'This is an authorized Route'})
})
usage of auth middleware without () works fine:
app.get('/products/:id', auth, function (req, res, next) {
res.json({msg: 'This is an authorized Route'})
})
Functions can return other functions, when you call the cors function using cors(), you get back a new function, that is used as the middleware function in app.get(). Your cors() example could be rewritten like so:
const corsMiddlewareFn = cors();
app.get('/products/:id', corsMiddlewareFn, function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
Above we store the function that calling cors() returns in a variable called corsMiddlewareFn, and then we use that as middleware as part of the call to app.get(). Having cors() return a function is useful as it allows us to pass options to the cors() function so that the middleware function it returns can use those options accordingly.
On the other hand, your auth function most likely doesn't return a function, so auth itself is the middleware function you want to use, and not its return value which you would get when calling auth().
The cors module returns a function that takes optional configuration and returns the middleware.
The auth is already the middleware, not a function, so no need to call it.
Related
I'm kind of new to express and node.js, and I can't figure out the difference between app.use and app.get. It seems like you can use both of them to send information. For example:
app.use('/',function(req, res,next) {
res.send('Hello');
next();
});
seems to be the same as this:
app.get('/', function (req,res) {
res.send('Hello');
});
app.use() is intended for binding middleware to your application. The path is a "mount" or "prefix" path and limits the middleware to only apply to any paths requested that begin with it. It can even be used to embed another application:
// subapp.js
var express = require('express');
var app = modules.exports = express();
// ...
// server.js
var express = require('express');
var app = express();
app.use('/subapp', require('./subapp'));
// ...
By specifying / as a "mount" path, app.use() will respond to any path that starts with /, which are all of them and regardless of HTTP verb used:
GET /
PUT /foo
POST /foo/bar
etc.
app.get(), on the other hand, is part of Express' application routing and is intended for matching and handling a specific route when requested with the GET HTTP verb:
GET /
And, the equivalent routing for your example of app.use() would actually be:
app.all(/^\/.*/, function (req, res) {
res.send('Hello');
});
(Update: Attempting to better demonstrate the differences.)
The routing methods, including app.get(), are convenience methods that help you align responses to requests more precisely. They also add in support for features like parameters and next('route').
Within each app.get() is a call to app.use(), so you can certainly do all of this with app.use() directly. But, doing so will often require (probably unnecessarily) reimplementing various amounts of boilerplate code.
Examples:
For simple, static routes:
app.get('/', function (req, res) {
// ...
});
vs.
app.use('/', function (req, res, next) {
if (req.method !== 'GET' || req.url !== '/')
return next();
// ...
});
With multiple handlers for the same route:
app.get('/', authorize('ADMIN'), function (req, res) {
// ...
});
vs.
const authorizeAdmin = authorize('ADMIN');
app.use('/', function (req, res, next) {
if (req.method !== 'GET' || req.url !== '/')
return next();
authorizeAdmin(req, res, function (err) {
if (err) return next(err);
// ...
});
});
With parameters:
app.get('/item/:id', function (req, res) {
let id = req.params.id;
// ...
});
vs.
const pathToRegExp = require('path-to-regexp');
function prepareParams(matches, pathKeys, previousParams) {
var params = previousParams || {};
// TODO: support repeating keys...
matches.slice(1).forEach(function (segment, index) {
let { name } = pathKeys[index];
params[name] = segment;
});
return params;
}
const itemIdKeys = [];
const itemIdPattern = pathToRegExp('/item/:id', itemIdKeys);
app.use('/', function (req, res, next) {
if (req.method !== 'GET') return next();
var urlMatch = itemIdPattern.exec(req.url);
if (!urlMatch) return next();
if (itemIdKeys && itemIdKeys.length)
req.params = prepareParams(urlMatch, itemIdKeys, req.params);
let id = req.params.id;
// ...
});
Note: Express' implementation of these features are contained in its Router, Layer, and Route.
Simply
app.use means “Run this on ALL requests”
app.get means “Run this on a GET request, for the given URL”
app.use is the "lower level" method from Connect, the middleware framework that Express depends on.
Here's my guideline:
Use app.get if you want to expose a GET method.
Use app.use if you want to add some middleware (a handler for the HTTP request before it arrives to the routes you've set up in Express), or if you'd like to make your routes modular (for example, expose a set of routes from an npm module that other web applications could use).
app.get is called when the HTTP method is set to GET, whereas app.use is called regardless of the HTTP method, and therefore defines a layer which is on top of all the other RESTful types which the express packages gives you access to.
Difference between app.use & app.get:
app.use → It is generally used for introducing middlewares in your application and can handle all type of HTTP requests.
app.get → It is only for handling GET HTTP requests.
Now, there is a confusion between app.use & app.all. No doubt, there is one thing common in them, that both can handle all kind of HTTP requests.
But there are some differences which recommend us to use app.use for middlewares and app.all for route handling.
app.use() → It takes only one callback.
app.all() → It can take multiple callbacks.
app.use() will only see whether url starts with specified path.
But, app.all() will match the complete path.
For example,
app.use( "/book" , middleware);
// will match /book
// will match /book/author
// will match /book/subject
app.all( "/book" , handler);
// will match /book
// won't match /book/author
// won't match /book/subject
app.all( "/book/*" , handler);
// won't match /book
// will match /book/author
// will match /book/subject
next() call inside the app.use() will call either the next middleware or any route handler, but next() call inside app.all() will invoke the next route handler (app.all(), app.get/post/put... etc.) only. If there is any middleware after, it will be skipped. So, it is advisable to put all the middlewares always above the route handlers.
In addition to the above explanations, what I experience:
app.use('/book', handler);
will match all requests beginning with '/book' as URL. so it also matches '/book/1' or '/book/2'
app.get('/book')
matches only GET request with exact match. It will not handle URLs like '/book/1' or '/book/2'
So, if you want a global handler that handles all of your routes, then app.use('/') is the option. app.get('/') will handle only the root URL.
There are 3 main differences I have found till now. The 3rd one is not so obvious and you may find it interesting. The differences are the same for the express router. That means router.use() and router.get() or other post, put, all, etc methods has also same difference.
1
app.use(path, callback) will respond to any HTTP request.
app.get(path, callback) will only respond to GET HTTP request. In the same way, post, put, etc will respond to their corresponding request. app.all() responds to any HTTP request so app.use() and app.all() are the same in this part.
2
app.use(path, callback) will match the prefix of the request path and responds if any prefix of the request path matches the path parameter. Such as if the path parameter is "/", then it will match "/", "/about", "/users/123" etc.
app.get(path, callback) Here get will match the whole path. Same for other HTTP requests and app.all(). Such as, if the path parameter is "/", then it will only match "/".
3
next('route') doesn't work on the middleware/callback functions of app.use(). It works only on app.get(), app.all() and other similar function of other HTTP requests.
According to express documentation:
next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.
METHOD is the HTTP method of the request that the middleware function
handles (such as GET, PUT, or POST) in lowercase.
From here we will use the keyword METHOD instead of get, post, all, etc.
But what is next('route')?!
Let's see.
next('route')
we see, app.use() or app.METHOD() can take several callback/middleware functions.
From the express documentation:
Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.
If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.
So we see each middleware functions have to either call the next middleware function or end the response.
And this is same for app.use() and app.METHOD().
But sometimes in some conditions, you may want to skip all the next callback functions for the current route but also don't want to end the response right now. Because maybe there are other routes which should be matched. So to skip all the callback functions of the current route without ending the response, you can run next('route'). It will skip all the callback functions of the current route and search to match the next routes.
For Example (From express documentation):
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
res.send('special')
})
See, here in a certain condition(req.params.id === '0') we want to skip the next callback function but also don't want to end the response because there is another route of the same path parameter which will be matched and that route will send a special response. (Yeah, it is valid to use the same path parameter for the same METHOD several times. In such cases, all the routes will be matched until the response ends). So in such cases, we run the next('route') and all the callback function of the current route is skipped. Here if the condition is not met then we call the next callback function.
This next('route') behavior is only possible in the app.METHOD() functions.
Recalling from express documentation:
next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.
Since skipping all callback functions of the current route is not possible in app.use(), we should be careful here. We should only use the middleware functions in app.use() which need not be skipped in any condition. Because we either have to end the response or traverse all the callback functions from beginning to end, we can not skip them at all.
You may visit here for more information
app.use gets called every time a request is sent to the server.
Only thing is we should call it before handling get, put, post etc. requests
app.use(middleware);
function middleware(req, res, next)
{
console.log("Came in middleware function without arrow");
next();
}
app.get gets called only for get requests for given path.
app.get('/myget', myget_function);
function myget_function(req, res)
{
console.log("Came in function myget");
res.send('Hello World! from myget');
}
app.post gets called only for post requests for given path.
app.post('/mypost', mypost_function);
function mypost_function(req, res)
{
console.log("Came in function mypost");
res.send('Hello World! from mypost');
}
I'm trying to write express middleware to check the validity of a JWT in the Authorization header. This seems quite easy but I don't want it to run on all routes (e.g. not on login/signup routers).
So, I'd like to specify in the router declaration that a route should require a valid token. E.g. something like this
const controllers = require('../controllers');
module.exports = (app) => {
app.post('/auth/signup', controllers.auth.signup.post);
app.post('/auth/login', controllers.auth.login.post);
app.get('/teams', controllers.teams.get, {requiresToken:true});
};
Except, .post and .get don't take a third parameter and the controller only takes (req,res,next) parameters so I can't really see a way of passing startic data for each route. I'm sure I'm missing something simple
This is how i created a middleware to pass the data into
module.exports = function(options) {
return function (req, res, next) {
//write your code here
// here you can access options variable
console.log(options.data)
next();
}
}
How you call that middleware is like this
app.use(middleware({'data' : 'Test'}));
To use on route basis
app.post('/userRegistration', middleware({'data' : 'Test'}), (req, res) => {});
You can exclude the auth subroute from this middleware using negative lookup regexp:
const controllers = require('../controllers');
module.exports = (app) => {
app.use(/\/((?!auth).)*/, yourJwtTokenValidatorMethod); // replace with your jwt token validator middleware
app.post('/auth/signup', controllers.auth.signup.post);
app.post('/auth/login', controllers.auth.login.post);
app.get('/teams', controllers.teams.get, {requiresToken:true});
};
I've been trying a variety of setups for hot reloading and one that I've come across is the https://github.com/glenjamin/ultimate-hot-reloading-example/. Modifying this boilerplate code as a starting point, I've come across the following problem in my server code:
// server.js
import chokidar from 'chokidar';
import express from 'express';
const app = express();
// this is the middleware for handline all of my routes
app.use(function (req, res, next) {
require('./server/index')(req, res, next);
// if I commented out any additional routes, the setup would work fine
require('./server/foo')(req, res, next);
require('./server/catch-all')(req, res, next);
});
//this watches the server folder for changes
const watcher = chokidar.watch('./server');
watcher.on('ready', function () {
watcher.on('all', function () {
console.log("Clearing /server/ module cache from server");
Object.keys(require.cache).forEach(function (id) {
if (/[\/\\]server[\/\\]/.test(id)) delete require.cache[id];
});
});
});
app.listen(3000, 'localhost', function (err) {
if (err) throw err;
const addr = this.address();
console.log('Listening at http://%s:%d', addr.address, addr.port);
});
The above is the server code that handles clearing the cache by watching for changes with the chokidar module. If I have just one route required inside the app.use middleware function (which listens for every incoming request), I can get it to work. However if have multiple routes, the following error occurs:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
This is a common issue posted on stack overflow, but all of the solutions I've come across and attempted haven't worked. My route files are as follows:
//index.js
import express from 'express';
const router = express.Router();
router.get('/', (req, res, next) => {
res.send("greagrehgarhegrehuh").end();
return next('router');
});
module.exports = router;
//end of index.js
//foo.js
import express from 'express';
const router = express.Router();
router.get('/foo', (req, res, next) => {
res.send("foo").end();
return next('router');
});
module.exports = router;
//end of foo.js
//catch-all.js
import express from 'express';
const router = express.Router();
router.get('*', (req, res, next) => {
res.send("catch all").end();
return next('router');
});
module.exports = router;
// end of catch-all.js
All three routes do the same thing, bar the endpoint. So far I've explicitly called end on each to end the response, used return next('router') to skip the rest of the middleware functions and have also tried doing it without the above as well. Any ideas on what I'm missing here to get this working? Here's a github project that showcases the issue
https://github.com/RonanQuigley/express-chokidar-hot-reload
UPDATE
So I actually removed the next calls and seem to have almost got it working by doing the following:
app.use(function (req, res, next) {
require('./server/index')(req, res, next);
require('./server/foo')(req, res, next);
});
// a second app.use middleware, that does the same
// as the catch all // * router.get from my original post
app.use(function (req, res, next) {
app.get('*', (req, res) => res.send('catch all'));
})
However, I can't use this second app.use with another require call to a file with an express router like the others. So it seems that express runs through the middleware stack, reaches the * and tries to set the header twice.
The reason I need the * is normally if a user requests an endpoint that doesn't exist, Node correctly shows up with cannot GET/. However, for some reason, with the setup I've outlined express will then crash. My workaround is using * at the end of the middleware stack and I'd just use a res.redirect to send the user back to wherever, but this causes the above issue I've outlined in my original post. So not sure how to get around that one.
So currently I have either:
1) Hot reloading works without the require for a router.get('*'), but when the user navigates to an endpoint that doesn't exist, express will crash.
2) Hot reloading works with the app.get('*') inside a second app.use call, but I can't then use a router to move this into a separate file.
Okay, so posting this solution up for my own future reference and in case somebody else stumbles into this problem.
After speaking with the express devs, it turns out that this is indeed possible with a combination of the following:
// you need to use comma separated routes
app.use(
dynamic('./server/index'),
dynamic('./server/foo')
);
// require the library at runtime and apply the req, res, next arguments
function dynamic(lib) {
return function (req, res, next) {
return require(lib).apply(this, arguments)
}
}
In the case of webpack, this would break it as you can't use require as an expression. So use the following to get around that:
function createRoutes(router) {
const dynamic = (lib) => {
return function (req, res, next) {
// let webpack generate a regex expression from this require
// if we don't you would get a critical dependency warning
// which would result in the routes not being found
return require("./src/" + lib + ".js").apply(this, arguments);
}
}
router.use(
dynamic('index'),
dynamic('foo'),
);
return router;
}
Let's step back a bit and talk about middleware.
Say you have a function which runs some kind of middleware.
const runMiddleware = (req, res, next) => {
console.log(`this will run everytime a HTTP request comes in`);
}
Then to use that middleware within express:
app.use(runMiddleware);
Every time any (GET, POST, DELETE, etc) request comes in, this function is run.
Essentially you are doing the same thing below - You are wrapping three (3) route calls with a single function. This function is calling all of these routes at once, hence res is actually being sent 3 times in a row in the example below:
app.use(function (req, res, next) { // runs every time any request comes in
require('./server/index')(req, res, next); // res sent, ok
require('./server/foo')(req, res, next); // res sent, err
require('./server/catch-all')(req, res, next); // res sent, err
});
Here is a basic way of handling routes:
const index = require('./server/index');
const foo = require('./server/foo');
app.use('/', index);
app.use('/foo', foo);
// catch everything else
app.use(function (req, res) {
res.send('catch all');
})
I have a question on javascript syntax. Actually I came up with the coding while I was self-teaching MEAN stack tutorial (https://thinkster.io/mean-stack-tutorial#adding-authentication-via-passport). There is a very weired coding below.
})(req, res, next);
(req, res, next) seems arguments but no function utilize that arguments. Maybe I am not smart enough at this point so that I cannot see it.
Is there any guy who can help me on this? Thanks.
router.post('/login', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
passport.authenticate('local', function(err, user, info){
if(err){ return next(err); }
if(user){
return res.json({token: user.generateJWT()});
} else {
return res.status(401).json(info);
}
})(req, res, next);
});
To understand what's happening, you should know what "middleware" is in Express. It's a function that you can pass to Express that gets passed a request object, a response object, and a next function:
function middleware(req, res, next) {
...
}
With middleware, you can "tap" into the path that HTTP requests will follow through an Express application, and perform certain actions.
You might have already noticed that the middleware function signature looks a lot like your example code:
router.post('/login', function(req, res, next) { ... });
This is a route handler that gets called for POST requests to /login. Route handlers are similar to middleware, in that they get called with the same arguments and also perform certain actions (usually, next isn't used in route handlers, but it will still get passed as an argument).
You can "stack" middleware, too:
router.post('/login',
function (req, res, next) { ... }, // first middleware
function (req, res, next) { ... }, // second middleware
...
);
This is where next comes into play: if the first middleware isn't interested in the request, it can call next (which is a function) and the request will be passed to the second middleware (and if that middleware isn't interested in it, it can call next too, passing the request along all middleware in the app, until a middleware handles the request or it falls through, generating a 404 error, because there no middleware was found that could handle the request).
passport.authenticate() also returns a middleware function. It's usually used like this:
router.post('/login',
passport.authenticate(...),
function (req, res, next) { ... }
);
Which means that if you look at the stacking example, passport.authenticate() should return a function that accepts the three arguments req, res and next (and in fact, it does).
That means that the code above can be rewritten to this:
router.post('/login', function(req, res, next) {
passport.authenticate(...)(req, res, next);
});
Which matches the code in your question. Why you would want to call passport.authenticate() like that is a relatively advanced Passport topic.
EDIT: this is what passport.authentication, in very broad terms, looks like:
// a function that mimics what `passport.authenticate` does:
function myAuthenticate() {
return function (req, res, next) {
...some stuff...
next();
};
}
It's a function that returns a function. You can use it like this:
router.post('/login',
myAuthenticate(),
function (req, res, next) {
...
}
);
Which is (almost) the same as this:
router.post('/login',
function(req, res, next) { // <-- this is the function that got returned!
...some stuff...
next();
},
function(req, res, next) {
...
}
);
I'm new to Node and Express and I'm not sure how I can access req in a middleware function in a POST route. Do I need to pass it in as a parameter? There are other middleware functions in this route that access req but it is not being passed in. Overall, I'm guess I'm confused as to how req works...
The function I'm referring to is helpers.createPermissions()
My Route
app.post('/oauth/authorize/decision', login.ensureLoggedIn('connect/signin'), helpers.createPermissions(req), oauth2.server.decision());
The Function
exports.createPermissions = function(req) {
console.log(req);
};
The Error
ReferenceError: req is not defined
Middleware will always get passed three arguments: req, res and next.
So your middleware should look like this:
exports.createPermissions = function(req, res, next) {
console.log(req);
// TODO: make sure you eventually call either `next` or send back a response...
};
And you can use it like this:
app.post('/oauth/authorize/decision', login.ensureLoggedIn('connect/signin'), helpers.createPermissions, oauth2.server.decision());
In situations where you see middleware being called as a function, it's because you're not calling the middleware itself, but a function that's returning a middleware function. For example:
var myMiddlewareWrapper = function() {
// return the actual middleware handler:
return function(req, res, next) {
...
};
};
app.get('/', myMiddlewareWrapper(), ...);
This is usually done to pass extra options to the middleware handler (like with login.ensureLoggedIn()).