As we know, Express is not very good in handling async functions, in particular for the error handling.
I did define an asyncMiddleware as follows:
const asyncMiddleware = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
And then:
router.get('/', asyncMiddleware(myRouteHandler))
Is there a way to properly rewrite the middleware in order to make it usable directly by the Express router?
router.use(asyncMiddleware)
Koa supports promises natively, it's expected that Express 5 will do this as well.
Is there a way to properly rewrite the middleware in order to make it usable directly by the Express router?
There is no way. In order to do that, Express app and router (express.Router and express.Route classes) methods that use middlewares and route handlers should be monkey-patched to do what asyncMiddleware does.
Otherwise promise-based middlewares should be manually wrapped with a helper like asyncMiddleware.
Related
I've created a middleware for authentication on my nuxt application, and I want to call it inside a layout.
Problem is, I'm calling it like this:
export default {
middleware: 'auth',
and it is returning me the following warning:
callback-based asyncData, fetch or middleware calls are deprecated. Please switch to promises or async/await syntax
I'm new into the front-end world and I searched but couldn't find/understand how to implement this async/await syntax on my middleware call. Can you help me?
Thanks in advance.
Faced a similar problem. I also use middleware: ['lang'], I got such an error and for a long time could not understand why this happened, if I did not change anything in the code. It turned out that in lang.js I mistakenly receive the second argument req
export default async function ({ isHMR, app, store }, req) {
}
Only a function servermiddleware can take multiple arguments
module.exports = function (req, res, next) {
Somewhat new, please bear with me. Trying to use passport to authenticate only specific routes in a website. The routes are in a separate file called blog_a.js. I have the following functions created in the main server.js file:
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()){
return next()
}
res.redirect('/login')
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()){
return res.redirect('/')
}
next()
}
However, I'm trying to pass the above functions into the blog_a.js module, so I can use them as middleware to protect the routes within that module.
I have tried to use module.exports = {checkAuthenticated, checkNotAuthenticated} at the bottom of the main 'server.js' file, and then use a let server = require('../server.js') line to import these functions to the module that contains the routes I want to protect.
However, the above server variable comes back as undefined, and I've tried several permutations / destructuring methods to try to import it. All to no avail, I keep getting the routes failing due to the "undefined" object--Error: Route.get() requires a callback function but got a [object Undefined].
How can I set up the authentication in the server.js file but then pass its authentication functions to be used as middleware within an individual route file?
I looked at this solution, but it doesn't clearly explain how to get the middleware functions from one module--server.js--to another module--blog_a.js.
I got the following response on Patreon from Kyle of Web Dev Simplified, and it worked like a charm!
"You should be able to just create another file that is called authMiddleware.js or something like that. Then in that file define and export the functions at the end (module.exports = { function1, function2 }). Now in the places you need those functions you should be able to import them like so (const { function1, function2 } = require('./authMiddleware'))."
So I followed Kyle's advice and created the following separate file authMiddleware.js:
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()){
return next()
}
res.redirect('/login')
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()){
return res.redirect('/')
}
next()
}
module.exports = { checkAuthenticated, checkNotAuthenticated }
... and then used the following require statements to get access to the functions:
-in main server.js --> const {checkAuthenticated, checkNotAuthenticated} = require('./authMiddleware.js')
-in router file blog_a.js --> const {checkAuthenticated, checkNotAuthenticated} = require('../authMiddleware.js')
Thanks!
I created a service in express to send emails, now I'm implementing a middleware for jwt authentication, it is already working, now I would like this middleware to be called automatically for any api I have or the ones I will cre
I tried to do the following assignment on my root, checkToken is my function on middleware
const app = express();
app.use(checkToken, require('./middlewares'))
app.use(`${config.URL_BASE}/email`, require('./apis/email'))
.
.
.
currently to call the middleware i'm doing, its works very well
router.post('', middleware.checkToken, async function (req, res) {
const {
type: typeCode,
.
.
.
its works very well, but my other api dont call the middleware, i didn't want to explicitly call again
Other api
router.get('/health', async (req, res) => {
res.status(200).send({ message: 'Ready.' })
})
To have middleware called for all routes, just do an app.use(yourMiddleware) before any of the routes are defined.
To have middleware called for one set of routes, but not other routes, put all the routes you want the middleware to be called for on a particular router that has a path prefix that only matches a subset of your routes. Then execute the middleware on that router before any of its routes are defined.
Here's an example of the 2nd option:
const express = require('express');
const app = express();
// load and configure api router
app.use('/api', require('./apiRouter.js'));
app.listen(...);
Then, inside apiRouter.js:
const router = require('express').Router();
// middleware that is called for all api routes
router.use(myMiddleware);
// define api routes here
router.get('/list', ...)
module.exports = router;
router.use() mounts middleware for the routes served by the specific router.
router.use(checkToken)
router.get('/health', getHandler)
router.post('/', postHandler)
module.exports = router
I believe in express 4.0 this is the way for creating router-level middleware, is this a good approach creating multiple instance of express.Router?
var userRouter = express.Router();
var paymentRouter = express.Router();
userRouter.get("/login", function (req, res, next) {
res.send("okay this is route")
});
paymentRouter.get("/pay", function (req, res, next) {
res.send("okay this is route")
});
app.use("/user" ,userRouter);
app.use("/payment" ,paymentRouter);
Separate routers can be used to modularize your application.
In your case, it looks like you have (at least) two distinct parts of an API or web app, a user part and a payment part:
app.use("/user", userRouter);
app.use("/payment", paymentRouter);
It's perfectly reasonable to use two separate routers for this.
Usually, each router is modularized even further by placing them in separate modules, that contain the specifics for that router:
app.use("/user", require('./routers/user'));
app.use("/payment", require('./routers/payment'));
So you get a nice separation of concern.
The Express documentation also touches on this topic here.
Really depends on what you want to achieve.
The normal way is to have just one router that is used to define your routes.
Please explain better why you would like to have more routers.
I have an Express.js project where I am allowing plugins to be loaded and unloaded at runtime. Plugins have access to the Expess.js router stack to register their paths just like a normal script would such as:
var express = require('express');
var router = express.Router();
module.exports = function(projectCoreObject) {
function Plugin() { }
// Plugin initialize called when a plugin is loaded.
Plugin.Initialize = function (done) {
// Register the router..
projectCoreObject.app.use('/', router);
};
// GET - /test
router.get('/test', function(req, res, next) {
res.send('Success!');
});
return Plugin;
};
While this all works great, I have the issue with unloading plugins removing their router from the stack.
Is there a proper way to remove a full router object from Express.js' stack at runtime? I can do individual middleware using their names but with a route like this example shows, the name is just 'router' in the stack.
I resolved this by using a named function trick to take an anonymous function and turn it into a named one. This way I can remove the router by its name then.