Not getting any response - Express Validator - node.js

I'm using the latest version of express-validator for validation.
I'm not getting any response, However Old method i.e checkBody is working fine while new method i.e check('keyName') is not working properly.
Below is my code.
package.json
"express-validator": "^5.0.3",
routes.js
var authValidator = require('./../validation/auth.validation');
var routes = require('express').Router();
routes.post('/login', [
authValidator.validateLogin,
authValidator.checkValidationResult ], function (req, res) {
console.log('3');
//res.send("Some other stuffs");
}
);
module.exports = routes;
auth.validation.js
module.exports.validateLogin = validateLogin;
module.exports.checkValidationResult = checkValidationResult;
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
function validateLogin(req, res, next) {
console.log('1');
return [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED)
.isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({min: 1}).withMessage(messages.PASSWORD_REQUIRED),
]
}
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(
res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}
I've noticed that node js not able to go ahead from the function validateLogin in auth.validation.js.
Can anyone tell me what's wrong with above code.
Inside console, Only 1 is displaying.
I'm attaching screenShot for referance.

We need to use simple Array and don't need to create function.
Follow this link
Is it possible to do the validation in a separate file and not inline in the route? - GitHub for more details.
Code should be like this.
auth.validation.js
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
module.exports.validateLogin = [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED).isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({ min: 1 }).withMessage(messages.PASSWORD_REQUIRED),
];
module.exports.checkValidationResult = checkValidationResult;
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}
`

validateLogin and checkValidationResult are being applied as middlewares to your route. In middlewares you use next()method to call next middleware in the queue. Just like in your checkValidationResult.
In case of validateLogin, its not passing control to next middleware. But check method from express-validator v5 is itself a middleware method. Thus I guess it won't work correctly.
Please have a look at: https://github.com/ctavan/express-validator/issues/449
Try using following Code:
routes.js
var authValidator = require('./../validation/auth.validation');
var routes = require('express').Router();
var authValidations = authValidator.getAuthValidations();
routes.post('/login',
authValidations,
authValidator.checkValidationResult, function (req, res) {
console.log('3');
//res.send("Some other stuffs");
}
);
module.exports = routes;
auth.validations.js
module.exports.getAuthValidations = getAuthValidations;
module.exports.checkValidationResult = checkValidationResult;
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
function getAuthValidations(req, res, next) {
return [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED)
.isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({min: 1}).withMessage(messages.PASSWORD_REQUIRED),
]
}
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(
res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}

Related

Modified Req Url in Express middleware ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client

Hey guys I am facing the error Error "[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" when I am trying to modify the req.url in a express middleware.
My middleware
export function ModifyQueryMiddleware(config, Authconfig, Repo ){
const accessTokenMap = new Map();
return async (request, res, next) => {
const accessToken = request.header('authorization') as string;
if(!accessToken){
throw new HttpException(res, 403)
}
if(!accessTokenMap.get(accessToken)){
const JWKS = jose.createRemoteJWKSet(new URL(config.jkwsUri));
try {
const jwtVerifyResult = await jose.jwtVerify(accessToken.replace('Bearer ', ''), JWKS);
const {payload} = jwtVerifyResult;
accessTokenMap.set(accessToken, payload)
const aumParams = await authentication(payload, authConfig,Repo);
const queryRestrictionStrategy = QueryRestrictionStrategyFactory(aumParams, request)
queryBuilder(queryRestrictionStrategy)
next()
} catch(err){
}
}
const payload = accessTokenMap.get(accessToken);
const aumParams = await authentication(payload, authConfig, repo);
const queryRestrictionStrategy = QueryRestrictionStrategyFactory(aumParams, request)
queryBuilder(queryRestrictionStrategy)
next()
}
}
My queryBuilder:
export function queryBuilder(strategy: QueryRestrictionStrategy){
const {req, id} = strategy
if(req.url === '/someurl'){
req.url = `/someurl?${id}`
}
return
}
I am really confused as I don't modify the header of a response instead I am just modifying the query without the querybuilder the middleware works fine. I already looked at a few questions regarding this error however the res was there always modified.
Any help or tips would be really appreciated !
Your code can call next twice when !accessTokenMap.get(accessToken) is true. You have to return once that part of your code is handled:
if (!accessTokenMap.get(accessToken)) {
const JWKS = jose.createRemoteJWKSet(new URL(config.jkwsUri));
try {
...
next();
} catch(err) {
next(err); // make sure to pass the error along!
}
return;
}

Not able to return the response to index.js file

I have added simple git branch function related code in getgitbranches.js file.
Calling this method from index.js.
Facing difficulty in returning branch summary data to index.js file.
index.js
app.get('/GetGitBranches', (req, res) => {
var gitBranches
console.log('inside')
gitBranches = require('./getgitbranches.js')
console.log(gitBranches.showlog(req,res))
res.send(gitBranches.showlog(req,res))
}
getgitbranches.js
let branchSummary = {}
exports.showlog = function (req, res){
const gitVariable= require('simple-git/promise')()
var branchVariable=gitVariable.branch(['-r']);
branchVariable.then(function (data) {
branchSummary.result = data.all
giveback(data.all)
})
}
giveback = function (data){
//console.log("givaback"+data)
branchSummary.result =data;
console.log("Branch Summary Result"+ branchSummary.result)
return branchSummary.result;
}
You are trying to log the value which is resolved inside the promise you should either await untill the promise is resolved or use callback
index.js
app.get('/GetGitBranches', async (req, res) => {
var gitBranches
console.log('inside')
gitBranches = require('./getgitbranches.js')
const response = await gitBranches.showlog(req,res)
return res.send(response)
}
getGitBranches.js
let branchSummary = {}
exports.showlog = async function (req, res){
const gitVariable= require('simple-git/promise')()
const result = await gitVariable.branch(['-r']);
return giveback(result.all);
}
giveback = function (data){
//console.log("givaback"+data)
branchSummary.result =data;
console.log("Branch Summary Result"+ branchSummary.result)
return branchSummary.result;
}

Protect controller functions with session values in a extra function

I have some session values that describes if a user is an admin or not. currently I do something like this:
exports.DeleteUser = function (req, res) {
if(req.session == undefined || req.session.Lv < 80){
res.render("Login");
return;
}
//Code
res.render(...);
}
So if someone want to access the page and no session values or if the session value "Lv" is less than 80 the user would get to the login.
I have ~20 controller functions and writing that code block 20 times seems a bit to much.
What would be a efficient way to write this in a function? The only way I see would be a function with a return value true or false but then I still need an if with the "return" in it with would makes this only 1 row shorter.. Or can this be done Controller wide?
You can solve this issue following way :
// Session or valid user checker
// middleware function
// file : sessionChecker.js
const sessionChecker = (req, res, next) => {
if(req.session == undefined || req.session.Lv < 80){
res.redirect('/login');
}
else {
next();
}
};
module.exports = sessionChecker;
Router
const sessionChecker = require('./sessionChecker.js');
const blogController = require('./blogController.js');
const userController = require('./userController.js');
// use sessionChecker middleware for check session
router.get('/blogs', sessionChecker, blogController.index);
router.get('/users', sessionChecker, userController.index);
Controller
// File : blogController.js
const BlogController = module.exports = {
/**
* Index method
* #param req
* #param res
* #return {Promise<void>}
*/
index: async (req, res) => {
let data = {
pageTitle: "Blog Lists",
blogs : await blogRepo.get(req, res),
};
res.render('home', data);
}
}

Express.js Designing Error Handling

I'm stuck on how to design error handling in an Express.js application.
What are the best design practices to handle errors in Express?
To my understanding, I can handle errors in 2 different ways:
First way would be to use an error middleware and, when an error is thrown in a route, propagate the error to that error middleware. This means that we have to insert the logic of the error handler in the middleware itself (note, the middleware here was purposely kept simple).
app.post('/someapi', (req, res, next) => {
if(req.params.id == undefined) {
let err = new Error('ID is not defined');
return next(err);
}
// do something otherwise
});
app.use((err, req, res, next)=>{
// some error logic
res.status(err.status || 500).send(err);
});
Another option is to deal with the errors on the spot, when the error happens. This means that the logic must be in the route itself
app.post('/someapi', (req, res, next) => {
if(req.params.id == undefined) {
let err = new Error('ID is not defined');
// possibly add some logic
return res.status(ErrorCode).send(err.message);
}
// do something otherwise
});
What is the best approach, and what are the best design practices for this?
Thank you
I think there are much more extensive cases but the main idea is using middleware design. Add your validation logic to this middleware.
yourRouter.post('/message', routerValidator.messageValidator, yourController.saveMessage.bind(yourController));
Below is my sample structure;
// controller
const BaseRoute = require('../infra/base/BaseRoute');
const log = require('./../../utils/log-helper').getLogger('route-web');
const { ErrorTypes } = require('../infra/middlewares/ErrorMiddleware');
const GameService = require('../../service/GameService');
const { SystemMessages } = require('../../statics/default_types');
module.exports = class WebController {
constructor() {
this._logger = log;
this._gameService = new GameService();
}
getGameInfo(req, res) {
var self = this;
try {
const info = self._gameService.getGameInfo(req.body.query);
return BaseRoute.success(res, { info });
} catch (err) {
self._logger.error('Something went wrong while getting game information', err);
return BaseRoute.internalError(res, SystemMessages.GENERIC_ERROR, req.getErrorCode(ErrorTypes.UNHANDLED, 1));
}
}
};
// router index
const express = require('express');
const ErrorMiddleware = require('../infra/middlewares/ErrorMiddleware').ErrorMiddlewarePath;
const baseValidator = require('../infra/validators/BaseRouterValidator');
const AndroidController = require('./AndroidController');
const IosController = require('./IosController');
const WebController = require('./WebController');
const AndroidRouter = express.Router();
const IosRouter = express.Router();
const WebRouter = express.Router();
const androidController = new AndroidController();
const iosController = new IosController();
const webController = new WebController();
AndroidRouter.post('/message', ErrorMiddleware(1), baseValidator.teamQueryValidator, androidController.getGameInfo.bind(androidController));
IosRouter.post('/message', ErrorMiddleware(1), baseValidator.teamQueryValidator, iosController.getGameInfo.bind(iosController));
WebRouter.post('/message', ErrorMiddleware(1), baseValidator.teamQueryValidator, webController.getGameInfo.bind(webController));
module.exports = {
AndroidRouter,
IosRouter,
WebRouter
};
// validator
const log = require('../../../utils/log-helper').getLogger('route-validator-base');
const BaseRoute = require('../base/BaseRoute');
const _ErrorTypes = require('../middlewares/ErrorMiddleware').ErrorTypes;
function teamQueryValidator(req, res, next) {
if (!req.body || !req.body.query) {
const params = req.body ? JSON.stringify(req.body) : 'Empty';
log.error('Invalid Parameters req body', params);
return BaseRoute.httpError(res, 'Bir takım adı giriniz..', 400, req.getErrorCode(_ErrorTypes.VALIDATION, 1));
}
return next();
}
module.exports = {
teamQueryValidator
};
// app.js that assigns to express
this._router = require('./src/route/api/index');
this._ErrorMiddleware = require('./src/route/infra/middlewares/ErrorMiddleware').ErrorMiddlewareRouter;
this.app.use('/api/android', this._ErrorMiddleware(1), this._router.AndroidRouter);
this.app.use('/api/ios', this._ErrorMiddleware(2), this._router.AndroidRouter);
this.app.use('/api/web', this._ErrorMiddleware(3), this._router.WebRouter);
What are the best design practices to handle errors in Express?
There is no best design, it's all subjective.
To my understanding, I can handle errors in 2 different ways:
Correct. You used error middleware for the first and then handled the error directly in the route handler.
To me, it makes sense to separate out the error handling logic from the business logic. It makes for cleaner code. So the former (error middleware) would be better IMO.
You would have a different error handler for different errors.

regarding foodme project in github

hello i have a question regarding the foodme express example over github:
code:
var express = require('express');
var fs = require('fs');
var open = require('open');
var RestaurantRecord = require('./model').Restaurant;
var MemoryStorage = require('./storage').Memory;
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
var removeMenuItems = function(restaurant) {
var clone = {};
Object.getOwnPropertyNames(restaurant).forEach(function(key) {
if (key !== 'menuItems') {
clone[key] = restaurant[key];
}
});
return clone;
};
exports.start = function(PORT, STATIC_DIR, DATA_FILE, TEST_DIR) {
var app = express();
var storage = new MemoryStorage();
// log requests
app.use(express.logger('dev'));
// serve static files for demo client
app.use(express.static(STATIC_DIR));
// parse body into req.body
app.use(express.bodyParser());
// API
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
i don't understand where is the api folder. it doesn't exist and i don't understand how information is going in and out from there. i can't find it.
can someone please explain this to me?
another question:
there is a resource for the restaurant
foodMeApp.factory('Restaurant', function($resource) {
return $resource('/api/restaurant/:id', {id: '#id'});
});
and in the restaurant controller there is a query:
var allRestaurants = Restaurant.query(filterAndSortRestaurants);
and the following lines:
$scope.$watch('filter', filterAndSortRestaurants, true);
function filterAndSortRestaurants() {
$scope.restaurants = [];
// filter
angular.forEach(allRestaurants, function(item, key) {
if (filter.price && filter.price !== item.price) {
return;
}
if (filter.rating && filter.rating !== item.rating) {
return;
}
if (filter.cuisine.length && filter.cuisine.indexOf(item.cuisine) === -1) {
return;
}
$scope.restaurants.push(item);
});
// sort
$scope.restaurants.sort(function(a, b) {
if (a[filter.sortBy] > b[filter.sortBy]) {
return filter.sortAsc ? 1 : -1;
}
if (a[filter.sortBy] < b[filter.sortBy]) {
return filter.sortAsc ? -1 : 1;
}
return 0;
});
};
the things that isn't clear to me is:
how is that we are giving the query just a function without even activating it.
as i understand we should have passed the query somthing like:
{id: $routeParams.restaurantId}
but we only passed a reference to a function. that doesn't make any sense.
could someone elaborate on this?
thanks again.
var API_URL = '/api/restaurant';
var API_URL_ID = API_URL + '/:id';
var API_URL_ORDER = '/api/order';
These lines are just defining string constants that are plugged into Express further down. They're not a folder.
app.get(API_URL, function(req, res, next) {
res.send(200, storage.getAll().map(removeMenuItems));
});
So this function call to app.get(API_URL... is telling Express "Look out for GET requests that are pointed at the URL (your app's domain)/api/restaurant, and execute this function to handle such a request."
"api" is not a folder.
Every requests will pass through the app.get method.
This method will respond to the routes /api/restaurant as defined in the API_URL variable.

Resources