ExpressJS - Send a response from middleware - node.js

For every request that happens, I'd like to check if a parameter in the query string is set. If not, the application should send a certain message; otherwise, route as appropriate.
In app.js:
app.use(function(req,res,next){
if(req.query.key === undefined) {
res.send("Sorry!");
}
req.db = db;
next();
});
app.use('/', routes);
When '/' is requested without the param, Sorry! is displayed. However, my ExpressJS app crashes with this error:
Error: Can't set headers after they are sent.
I'm not entirely sure why this is happening. I've tried moving the check to the route itself in index.js, but I still get the same error.

That's because you're still continuing on with the execution and calling next(), which moves onto the next middleware or route in the stack.
Return early to stop it from moving onto the next middleware.
app.use(function(req,res,next){
if(req.query.key === undefined) {
//return out of the function here
return res.send("Sorry!");
}
req.db = db;
next();
});
app.use('/', routes);

Related

Why does the console.log appear twice in app.js in nodejs

I have written a code in NodeJS where when i hit the url, i need the server to pass through three middleware functions authentication, cookies, logging. Here it happens , but the console gets printed twice. Can you help me figure out why.
var express = require('express');
var app = express();
var router = require('express').Router();
/* Add the middleware to express app */
app.use (function authentication(req,res,next){
if(req.method === 'GET'){
console.log("Inside Authentication.js")
next(); // If your don't use next(), the mmand won't go to the next function.
}
else{
console.log("Inside else Authentication.js")
}
})
app.use( function cookies(req,res,next){
if (req.method === 'GET'){
console.log("Inside cookies.js")
next();
}
else
{
console.log("Inside else cookies.js")
}
})
app.use( function logging(req,res,next){
if(req.method === 'GET'){
console.log("Inside Logging.js");
next();
}
else{
console.log("Inside else of Logging.js");
}
})
app.use(function(req,res) {
res.send('Hello there !');
});
app.listen(8080);
o/ p -
E:\NodeJSProject\middleware>node app.js
Inside Authentication.js
Inside cookies.js
Inside Logging.js
Inside Authentication.js
Inside cookies.js
Inside Logging.js
Your browser will perform a pre-flight CORS request (i.e. an OPTION request) to see whether you're allow to perform the request.
From your perspective its just one request, but the browser is performing two requests and your express server is executing both requests in full.
Given you're using express there is middleware available to handle those requests specifically.
See here for documentation.
If you want to avoid the CORS request altogether, your website and API need to be served from the same host, port, and protocol.
You can read more about CORS here, or you can search Stack -- theres extensive posts.

skip token verification for GET request

I want skip token verification for GET method in express. I want to allow GET request for everyone while just post, put, delete request by authorized user.below is my logic but the response hanging. I tried to used nested express use method.
app.use(function(req, res, next) {
if (req.method === 'GET') {
app.use('/api/someroute', routes);
}
else{
//do verification below the next
next();
}
})
or is there any other way to handle this
Just include a middleware on desired routes :
var router = express.Router();
// no middleware included for get request
router.get("/route1", handlerRoute1);
router.get("/route2", handlerRoute2);
// include some middleware
router.post("/route3", myMiddleware1, myMiddleware2, handlerRoute3);
app.use(router);
Where myMiddleware1 and myMiddleware2 looks like :
myMiddleware1 = function(req, res, next){
// verify token, etc, ....
var success = true;
// call next on success
if(success)
return next();
else
{
// raise error
return res.status(500).json({error: "Missing token..."});
}
};
It's because in the scenario for GET requests you don't actually complete the request (or move on from that middleware). Middleware is processed in sequential order i.e. first come first served. If you only want to protect everything other than GET requests then something like this would be fine:
app.use(function(req, res, next) {
// let GET requests through
if (req.method === 'GET') return next();
// perform token auth on all other requests, next() if OK
});
// setup routes
app.use('/api/someroute', routes);
You would setup your middleware first then declare your routes after, this means any requests coming in will have to pass through your token check, in this case you just skip GET requests.

koa-static going to next middleware

I have a koa 2 server.
The following code are my middlewares:
// parse body
app.use( bodyParser() )
// serve static
app.use( serve( path.join(__dirname, '/public') ) )
// routes
app.use( routes )
// error middleware
app.use( async ctx => ctx.throw(500) )
Everything works well but my problem is that when I go to localhost:8000, where my server lives, in the console I see the following error:
InternalServerError: Internal Server Error
at Object.throw (/Users/work/Desktop/server/node_modules/koa/lib/context.js:91:23)
I'm suspecting that after static, the app is going to the next middleware, which is the error middleware.
PS. I'm using app.use( async ctx => ctx.throw(500) ), to call next() if I'm getting errors on the other routes.
Does anyone know how to fix this?
Thanks!
I'm suspecting that after static, the app is going to the next
middleware, which is the error middleware.
koa-static transfers control to the next middleware by design.
Your routes middleware also await to the next middleware.
So you get an error.
Does anyone know how to fix this?
It's hard to say what you are going to achieve in the first place.
Setting 500 manually is probably a wrong idea. There should be 404 like:
// 404 middleware
app.use(async ({response}, next) => {
if (!this.body) {
response.status = 404
response.body = "Not Found" // or use template
}
await next() // send control flow back (upstream)
})
For SPA (without SSR) you probably want this catch-all route to send APP layout instead. And move that 404 middleware to the beginning of the file (where it will take control on the second "bubbling" phase.
Make sure you checked this
use like, you add a middleware to handle your custom error properly...
// serve static
app.use(serve(path.join(__dirname, '/public')))
// error middleware
app.use(async(ctx, next) => {
try {
await next();
} catch (e) {
console.log(e.message);
ctx.body = e.message
} finally {}
})
// routes
app.use(router.routes()).use(router.allowedMethods());
router.get('/a', ctx => {
try {
ctx.body = "sadsa"
} catch (e) {
ctx.body = e
console.log(e);
} finally {}
});
app.use(ctx => ctx.throw(500))
app.listen(7000)

After sending response, how to end the current request processing in Node/Express?

There are a few posts on this question but none that answers the issue directly, head-on. Let me clarify that I understand (or so I think) the use of next(), next('route'), return next(), return and their impact on control flow.
My entire middleware for the app consists of a series of app.use, as in:
app.use(f1);
app.use(f2);
app.use(f3);
app.use(f4);
...
In each of these middlewares, I have possibility of sending the response and be done without any need for further processing. My problem is that I am unable to stop the processing from going to the next middleware.
I have a clumsy work around. I just set a res.locals.completed flag after sending a response. In all the middlewares, at the very start, I check this flag and skip processing in the middleware if the flag is set. In the very first middleware, this flag is unset.
Surely, there must be a better solution, what is it? I would think that Express implicitly would do this checking and skip the middlewares through some express-specific method?
According to the express documentation on http://expressjs.com/guide/using-middleware.html
If the current middleware does not end the request-response cycle,
it must call next() to pass control to the next middleware,
otherwise the request will be left hanging.
so if a middleware needs to end the request-response early, simply do not call next() but make sure that the middleware really ends the request-response by calling res.end, res.send, res.render or any method that implicitely calls res.end
app.use(function (req, res, next) {
if (/* stop here */) {
res.end();
} else {
next();
}
});
Here is an example server showing that it works
var express = require('express');
var app = express();
var count = 0;
app.use(function(req, res, next) {
console.log('f1');
next();
})
app.use(function(req, res, next) {
console.log('f2');
if (count > 1) {
res.send('Bye');
} else {
next();
}
})
app.use(function(req, res, next) {
console.log('f3');
count++;
next();
})
app.get('/', function (req, res) {
res.send('Hello World: ' + count);
});
var server = app.listen(3000);
you will see the after 3 requests, the server shows "Bye" and f3 is not reached

How to exit from a stack of middleware in Express.js

I am working a REST web application backend and I got some problem when linking my middleware together.
For example, the stack of the middlewares that each request has to go through is like [before1, service, after1], and here's the code for the middleware "before1", this is just the code I used for testing:
'use strict';
var express = require('express');
var router = express.Router();
router.use(function(request, response, next){
console.log('This is middleware BEFORE1');
var success = true
if (!success){
// Go the logging middleware underneath
next();
}
else{
// Go to the 'service' middleware
next('route');
}
})
router.use(function(request, response, next){
console.log('This is middleware LOGGING');
response.sendStatus(400);
response.end();
})
module.exports = router;
The above code is simply saying if the 'before1' succeeds, it should go straight to call 'service' middleware, and otherwise go to the logging middleware underneath and end the request. But my problem is that I can't figure out a way that it could skip the logging middleware, I searched and found next('route') could help, but it didn't work here. What have I missed?
Thanks in advance!
EDIT:
Or more preferably, it's the best if I can issue an error in any of my middleware and handle all types of errors properly using a error handler middleware.
The skeleton of my top level code is the following:
// An array of middleware to be executed asynchronously
operations = [before1, service, before2];
async.series(operations, function(err) {
if(err) {
// one of the functions passed back an error so handle it here
console.log('Handling error!!!!');
res.end();
// return next(err);
}
console.log('middleware get executed');
// no errors so pass control back to express
next();
});
But I am not sure How should change my middlewares accordingly in order to do that.
next is a node-style callback, which means fn(err, ..), so your next('route') will only work to invoke errorhandlers.
You can implement your series directly by supplying an array of functions to the route, and using an express error handler as the catch all (see http://expressjs.com/guide/error-handling.html)

Resources