node-restify parent path handler - node.js

If I have two path, let's say /path/one and path/two, and I wan't they both handled by a parent handler first, then handled by their specific handler. How can I achieve it. The code below won't work. Their specific handler never run.
const restify = require('restify');
const app = restify.createServer();
app.get('/path/:type', function (req, res, next) {
console.log(req.params.type + ' handled by parent handler');
next();
});
app.get('/path/one', function (req, res) {
console.log('one handler');
res.end();
});
app.get('/path/two', function (req, res) {
console.log('two handler');
res.end();
});
app.listen(80, function () {
console.log('Server running');
});

Unfortunately this kind of "fall through routing" is not supported in restify. The first route handler that matches the request is executed. But you have some alternatives to implement the given use case
Named next Calls
Instead of calling next() without a parameter you call next(req.params.type) to invoke route one or two. Caveats: In case no route is registered for a type restify will send a 500 response.
const restify = require('restify');
const app = restify.createServer();
app.get('/path/:type', function (req, res, next) {
console.log(req.params.type + ' handled by parent handler');
next(req.params.type);
});
app.get({ name: 'one', path: '/path/one' }, function (req, res) {
console.log('one handler');
res.end();
});
app.get({ name: 'two', path: '/path/two' }, function (req, res) {
console.log('two handler');
res.end();
});
app.listen(80, function () {
console.log('Server running');
});
Common handlers (aka Middleware in express)
Since restify has no mounting feature like express does we need to extract the type param from the current route manually:
const restify = require('restify');
const app = restify.createServer();
app.use(function (req, res, next) {
if (req.method == 'GET' && req.route && req.route.path.indexOf('/path') == 0) {
var type = req.route.path.split('/')[2];
console.log(type + ' handled by parent handler');
}
next();
});
app.get('/path/one', function (req, res) {
console.log('one handler');
res.end();
});
app.get('/path/two', function (req, res) {
console.log('two handler');
res.end();
});
app.listen(80, function () {
console.log('Server running');
});

Related

Error handling problem with Nodejs and Express

I'm trying to handle errors produced in a Nodejs with Express app. I'm following Express error-handling guide but the errors didn't catched, and nothing appears on console and browser simply show Cannot GET /abc when request the incorrect url http://localhost:3000/abc
const express = require("express")
const app = express()
const port = 3000
const config = require("./config.js");
function logErrors (err, req, res, next) {
console.error(err.stack)
next(err)
}
function errorHandler (err, req, res, next) {
res.status(500)
res.render("error", { error: err })
}
app.all("/", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
app.get("/favicon.ico", (req, res) => res.status(204));
app.use(express.static("public"))
app.use("/zips/:idReq", express.static("zips"))
const generateZip = require("./generateZip")
const fmeForm = require("./fmeForm")
app.get("/", function (req, res) {
res.send("Hello World !")
})
app.use("/generateZip", generateZip)
app.use("/downloadForm", fmeForm)
app.use(logErrors)
app.use(errorHandler)
app.listen(port, () => console.log(`${config.nameServer} App listening on port ${port}`))
Any idea?
You need to include a common route handler to invoke error handling method at last
app.all('*', function (req, res, next) {
// Either invoke error handler method by raising new error
next(new Error('page not found'));
// Or simply return the response
res.status(404).send('page not found')
})

how to implement middleware in socket.io like express in NodeJS?

How to implement middleware like this in socket.io? Please help
EXPRESS APP
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
SOCKET APP (I am using express pattern but its not working)
var myLogger = function (data,next) {
console.log('DOING DATA VALIDATION...')
next()
}
io.use(myLogger)
io.on('someEvent/', function (data, callback) {
callback('Hello World!')
})
Error : next() is not define!
app.use(function (req, res, next) {
req.io = io;
next();
});
This assigns a socket object to every request.
If somebody's still wondering.
To use middleware on all sockets:
io.use((socket, next) => {
// isValid is just a dummy function
if (isValid(socket.request)) {
next();
} else {
next(new Error("invalid"));
}
});
This example is from the official docs of socket.io
To use a middleware for a specific client:
io.on('connection', async (client) => {
client.use((socket, next) => {
console.log(`got event: ${socket[0]} in client middleware, moving on with next() just like in express`)
next()
});
// rest of your code
newConnection(client)
})

created a simple middleware game with Nodejs, and an http header error occurs

I am a beginner studying Nodejs.
I have recently studied node middleware and have created a simple game using middleware.
The purpose of the generated code is to respond to hello by connecting as root and then respond to the browser with 50% probability through the middleware.
However, I get the following error:
I did a search and found that res.send is not available after next ().
Is that correct?
But I could not figure out why and I did not realize why the code did not work.
code
const express = require('express');
var app = express();
app.use('/', (req, res, next) =>{
res.send('hello');
next();
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.listen(3000, () => console.log(`Example!`))
error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const express = require('express');
var app = express();
app.use(/^\/$/, (req, res, next) =>{
res.send('hello');
return;
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.listen(3000, () => console.log(`Example!`))
you cannot use res.send() twice
res.send() = Sends the HTTP response.

next() omits middleware sub-stack in route.param

In below example for GET /api/users/i request secondMw is never executed even there is a next() call in firstMw. Why is that? How am I supposed to be able to run the secondMw?
var apiRouter = require('express').Router();
apiRouter.param('user', function firstMw(req, res, next, param) {
if(param === 'i'){
return next(); //jump to next mw sub-stack
}
next('route'); //continue with another matching route
}, function secondMw(req, res, next, param) {
console.log('NO, I AM NOT HERE. NEVER');
next();
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({
id: req.params.user
});
});
app.use('/api', apiRouter);
I don't see that router.params supports middleware stack (compare definition with app.get). But you can use ordered definition for same route.
'use strict';
let express = require('express');
let app = express();
app.use(require('body-parser').urlencoded({extended: false}));
var apiRouter = express.Router();
apiRouter.param('user', function mw1(req, res, next, param) {
console.log('MW1', param);
if (param === 'i')
next();
else
next('Error message'); // better next( new Error('Error message'));
});
apiRouter.param('user', function mw2(req, res, next, param) {
console.log('MW2', param);
next();
})
// If next() have params then Express calls handler error
apiRouter.use(function (err, req, res, next) {
console.log('Error: ', err)
res.send(err.message || err);
});
apiRouter.get('/users/:user', function (req, res, next) {
res.json({id: req.params.user});
});
app.use('/api', apiRouter);
app.listen(3000, function () {
console.log('Listening on port 3000');
});

how to group api in express

Here is the example:
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
//code
});
app.post('/user/register', function(req, res) {
//code
})
app.put('/user/register', validateToken, function(req, res) {
//code
})
app.delete('/user/delete', validateToken, function(req, res) {
//code
})
If I have 10 api that need validToken, I should add validToken middleware 10 times, like:
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
....
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
How can I group api by using the same middleware?
Here's how to re-use the same callback function for multiple routes (like middleware):
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
// code
});
app.post('/user/register', function(req, res) {
// code
});
// Be sure to specify the 'next' object when using more than one callback function.
app.put('/user/register', validateToken, function(req, res, next) {
// code
next();
});
app.delete('/user/delete', validateToken, function(req, res, next) {
// code
next();
});
Also, you can replace app.METHOD (e.g. .post, .get, .put, etc.) with app.all and your callback will be executed for any request type.
Just wrong, so do not put into mass participation of the (Google translated from: 刚才看错了,改成这样就不用放进传参了)
var group = {url:true,url:true,url:true};
app.use(function(req,res,next){
if(group[req.url]){
// Do something with request here
next();
} else {
next();
}
})

Resources