If router.all() just match all methods,could it be instead by router.use()?
and what router.use() diff between router.route()?
router.all: What this means is, it doesn't matter the method of the request.. (post, get, put), if the url matches, execute the function.
ex- router.all("/abc",fn) will be work for all request to /abc
router.use() : router.use() helps you write modular routes and modules.. You basically define a middle ware for routes.
router.use("/pqr", pqrRoutes)
now for all requests that start with /pqr like /pqr/new or /pqr/xyz can be handles inside the pqrRoutes.
router.route(): this is nice way to define the different Method implementations for a single url end point.
lets just say you have two api end points. router.get("/jkl") and router.post("/jkl"), with router.route() you cam sort of combine these different api handlers..
you can say router.route("/jkl").get(fn1).post(fn2)
router.all() matches every http protocol, router.use() is for middleware, and router.route() returns an instance of a single route which you can then use to handle HTTP verbs with optional middleware.
You should check out the documentation for more informations
app.all(), which is not derived from any HTTP method. This method is used for loading middleware functions at a path for all request methods.
app.all('/secret', function (req, res, next) {
console.log('Accessing the secret section ...')
next() // pass control to the next handler
})
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”.
The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.
var express = require('express')
var router = express.Router()
// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
console.log('Time: ', Date.now())
next()
})
Bascially we use .use when we use a middleware
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”.
The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.
var express = require('express')
var router = express.Router()
// middleware 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('Birds home page')
})
There can we more than 1 router this instance of router has name router defined below the express defination.
Here is the documentation for router
https://expressjs.com/en/guide/routing.html
Router.use()
Routers behave like middleware and can be .use()d by the app in other routers. In other words, routers allow you to chunk your big app into numerous mini-apps that you can later put together. For small apps, this might be overkill, but as soon as you think, “This app.js file is getting big,” it’s time to think about breaking down your app with routers.
router.route(path)
The router.route(path) method is used to chain HTTP verb methods. For example, in a create, read, update, and
delete (CRUD) server that has POST, GET, PUT, and DELETE endpoints for the /posts/:id URL (e.g., /posts/53fb401
dc96c1caa7b78bbdb), we can use the Router class as follows:
var express = require('express');
var router = express.Router();
router.param('postId', function(request, response, next) {
// Find post by ID
// Save post to request
request.post = {
name: 'Node.js',
url: 'http://your-url/node-js-blog'
};
return next();
});
The Router.route(path) method provides the convenience of chaining methods, which is a more appealing way
to structure, your code than re-typing router for each route.
Alternatively, we can use router.VERB(path, [callback...], callback) to define the routes just as we
would use app.VERB(). Similarly, the router.use() and router.param() methods work the same as app.use() and
app.param().
Related
I've been playing around with setting up a basic atlassian-connect-express (ACE) application, and have modified the starter code provided by the ACE package to be suitable for serverless deployment. One of the problems I faced after doing this was that routing is now divided into stages, e.g. /dev, /prod. I did a bit of research and found that a way to deal with this would be to use an express Router and mount it to the appropriate endpoint for the stage being deployed to. The problem I then faced is that the authentication middleware provided by ACE seems to be application level and then can't be used by each router.
Typically the routes were added to the express app like this:
import ace from 'atlassian-connect-express';
import express from 'express';
import routes from './routes';
const app = express();
const addon = ace(app);
app.use(addon.middleware());
routes(app, addon);
and in ./routes/index.js
export default function routes(app, addon) {
// Redirect root path to /atlassian-connect.json,
// which will be served by atlassian-connect-express.
app.get('/', (req, res) => {
res.redirect('/atlassian-connect.json');
});
// This is an example route used by "generalPages" module (see atlassian-connect.json).
// Verify that the incoming request is authenticated with Atlassian Connect.
app.get('/hello-world', addon.authenticate(), (req, res) => {
// Rendering a template is easy; the render method takes two params:
// name of template and a json object to pass the context in.
res.render('hello-world', {
title: 'Atlassian Connect'
});
});
// Add additional route handlers here...
}
I've changed ./routes/index.js to work as a router object and export that, however this leaves me unable to use the addon.authenticate() middleware
import ace from 'atlassian-connect-express';
import express from 'express';
import routes from './routes';
const app = express();
const addon = ace(app);
app.use('/dev', require('./routes'));
and in ./routes/index.js
const express = require('express');
const router = express.Router();
// Redirect root path to /atlassian-connect.json,
// which will be served by atlassian-connect-express.
router.get('/', (req, res) => {
res.redirect('/atlassian-connect.json');
});
// This is an example route used by "generalPages" module (see atlassian-connect.json).
// Verify that the incoming request is authenticated with Atlassian Connect.
router.get('/hello-world', addon.authenticate(), (req, res) => {
// Rendering a template is easy; the render method takes two params:
// name of template and a json object to pass the context in.
res.render('hello-world', {
title: 'Atlassian Connect'
});
});
module.exports = router;
Obviously having no knowledge of addon, the router cannot use that authentication middleware.
Is it possible to pass that middleware through to the router when attaching it to the application? If not, is there another way I can handle URL prefixes without using a router?
I have multiple app.use in my index/starting point of my app.
i.e
app.use(
if (!req.contextToken && req.contextTokenchecked) {
req.queryToFirebase = false;
req.contextTokenchecked = true;
req.contextToken = {}
}
next()
)
app.use(//Do something 2)
and so on..
Now, This is sort of makes my code untidy (in index.js) so I thought about creating a separate js file (say intialize.js) which will contain all my app.use
Till now, I am used to only creating separate routes
const express = require('express')
const router = express.Router()
and then import it in my index.js
app.use('/auth', auth)
But this time I don't want my routes in separate file rather all
app.use()
In one common.js file
Second, I also have a route which loads data from gmail (gmail.js).
app.use('/gmail', gmail)
currently, In all the routes, I am adding a middleware isLoggedInmanually. Is it possible to do something so that all the routes inside it my gmail.js inherits that middleware
The middlewares you register are always executed in the order they are registered. So if you have a code like this:
app.use((req, res, next) => {
// middleware A
next()
})
app.use((req, res, next) => {
// middleware B
next()
})
app.use(middlewareC)
app.use('/gmail', gmail)
Then you can for sure create one common file for those middlewares before the app.use('/gmail', gmail):
common.js
let router = express.Router()
router.use((req, res, next) => {
// middleware A
next()
})
router.use((req, res, next) => {
// middleware B
next()
})
router.use(middlewareC)
module.exports = router
main.js
app.use(require('./common.js'))
app.use('/gmail', gmail)
The API for use (or any others of those registering methods) is ([path,] callback [, callback...])
So you can register as many middlewares as callback as you want, so you can add a isLoggedIn in front of the gmail router:
app.use('/gmail', isLoggedIn, gmail)
I am creating an express middleware. My index.js exports is a function that returns a function(req,res,next) {...}
function myMiddleware (options) {
//some stuff with options...
return function middleware(req, res, next) {
//stuff
}
}
module.exports = myMiddleware;
So the user would could start using my middleware like this:
var express = require('express'),
myMiddleware = require('my-middleware'),
app = express();
app.use(myMiddleware());
The important thing is that I must make sure that middleware has access to cookies. Of course I could parse req.header.cookie myself but there exists a cookie-parser module that does the parsing for me.
So I would like to make sure that cookie-parser middleware is already being used when my middleware starts up. I could probably instruct the user to first use cookieParser() but I dislike it.
Is there a way to do it easily?
EDIT
I could even port cookie-parser since it is not a huge module. But that is probably the least thing I would do since it can introduce a lot of maintenance work that I would normally not do.
You have two options:
Force the cookie-parser middleware if req.cookies is undefined.
If cookie-parser has already been called, this call will be ignored. See: https://github.com/expressjs/cookie-parser/blob/master/index.js
The downfall to this approach is that the cookieParser middleware will only have the default options.
var cookieParser = require('cookie-parser');
function myMiddleware(options) {
return function(req, res, next) {
return cookieParser()(req, res, function() {
// Your middleware code
return next();
});
}
}
Give a warning if req.cookies is undefined
function myMiddleware(options) {
return function(req, res, next) {
if(!req.cookies) {
// Some warning
}
// Your middleware code
return next();
}
}
In express, the execution order of middleware is defined by the order it has been attached to the app/router.
req.param being an exception, as it is executed before any route handler that matches the parameter.
The order in which your routes and middleware functions are declared is the order which they will be executed. I do not know of a way to change this, maybe fiddling with the internals of express router, but there is no documented/clean way to achive this by default.
To make sure your middleware has access to the cookie parsed by cookie-parser, attach the cookie parsing middleware before any route definitions.
app.use(cookieParser());
// all other middleware that uses cookies
I'm attempting to use the Express 4 Router to use a different router based on the path. I want all /api/v2/ routes handled by version2, and every other route handled by version1. The below setup serves me all the version1 routes correctly, but seems to ignore version2 as I get a 'Cannot GET...' message each time I test those endpoints.
routes.js:
var version1 = require('./routes/vers1');
var version2 = require('./routes/vers2');
module.exports = function(app) {
app.all('/api/v2/*', version2);
app.all('/*', version1);
};
Method routes (.get, .post, and of course .all) are terminal. This is why you can use wildcards with them as well. .use is not terminal and doesn't allow wildcards -- it acts as a prefix. This is an implementation choice of express. Use .use without wildcards.
.use does not set the layer route
all other methods set the layer route
if the route is set, layer attempts to handle the request. Otherwise, the layer's path is stripped from the request route (/api/v2 that you set in .use will be stripped).
The fact that app.use("/*", version1) works is purely incidental. This will match any route and fall through to version1[method](path). Since there is no prefix to strip, if the request route matches path, express will consider this a match and serve that route.
Use .use.
You want to use .use not .all
.all is for middleware like authentication
http://expressjs.com/api.html
I have created a custom route middle ware for express js.
Example:
var customRouter = function(req, res, next) {
console.log(res);
next();
};
and in app.js
app.use(app.router); //express default router
app.use(customRouter); //my custom router which comes after express default router
My custom router comes after the express default router. What I'm trying to achieve is that to determine if the default express router have already rendered a response or a view.
How do I determine in my route middleware if a view or a response is already rendered in the express route?
As far as I know, when a middleware sends a response, then next() is not called anymore. So your customRouter is not fired in a case, when default router handles a request.
But anyway, you can always check a response if it was already flushed: res.finished => (boolean)