2012-09-23 57 views
6

Estoy construyendo una aplicación exprés y me gustaría saber lo sofisticado que puedo llegar con el middleware. A grandes rasgos, quiero lograr lo siguiente con middleware.Node.js middleware organización y validación de parámetros

Hecho:

  • Añadir RequestID a todas las rutas de solicitud
  • Autenticación
  • Comprobar si un usuario tiene acceso a un determinado recurso (aparte de autenticación)

no se realiza:

  • A) parámetros Validar para una ruta dada
  • B) Organizar middleware de una manera sana, si éste difiere de la ruta a la ruta, y 3 middlewares se llaman habitualmente por ruta

he definido mi middleware en un archivo separado, y la importación en app.js así:

var middleware = require('./middleware'); 
var requestId = middleware.requestId; 
var authenticate = middleware.authenticate; 

aplicarlo a todas las rutas que añadirlo a expresar config:

var app = express.createServer(); 
app.configure(function() { 
    app.use(express.logger()); 
    app.use(express.cookieParser()); 
    app.use(express.bodyParser()); 
    app.use(requestId); // add requestId to all incoming requests 
}); 

Y para obtener información específica de ruta, lo añado como argumento app.get:

var routes = require('./v1/routes'); 
app.get("/v1/foo", routes.foo); 
app.get("/v1/bar", authenticate, routes.bar); 

Problema Un

Me encantaría tener middleware que podría utilizar para comprobar los parámetros

validate('x','y','z') 

y utilizarlo como tal para una ruta determinada:

app.get("/v1/bar", authenticate, validate('x','y','z'), routes.bar); 

¿Hay una buena manera de hacerlo? ¿O debería simplemente estar validando por ruta dentro de los archivos de definición de ruta?

Problema B

¿Hay una mejor manera de organizar y usar mi middleware que debería tener en cuenta?

actualización

Busco una manera de validar los parámetros que cambian mucho entre rutas. Evidentemente, lo que sigue no funciona, no puedo pasar los parámetros al middleware, pero ¿hay alguna manera de definir el middleware que hace esto y llamarlo como ya he dicho?

var validateParams = function (req, res, params, callback) { 
    // Make sure the required parameters are in the request 
    console.log('checking for params '+params); 
    for (var i = 0; i < params.length; i++) { 
    var param = params[i]; 
    if(!(param in req.query)){ 
     logger.info('cannot find param ['+param+'] in req: '+JSON.stringify(req.query)); 
     res.writeHead(400, { 
     "Content-Type": "application/json" 
     }); 
     var out = { 
     "err": "request missing required parameters" 
     }; 
     res.end(JSON.stringify(out)); 
     return;  
    } 
    } 
    callback(); 
} 
+0

Querrá pasar req, res a su middleware así que valide (req, res) y luego actúe desde allí. Usualmente eso es más simple que pasar variables predeterminadas. – Brandon

+0

Prueba a buscar en el validador expreso. No lo he usado en middleware, pero parece posible: https://github.com/ctavan/express-validator – chovy

Respuesta

2

Problema Un

app.get("/v1/bar", authenticate, validate, routes.bar); 

function validate(req,res,next){ 

//Get all parameters here by req.params and req.body.parameter 
//validate them and return. 
if(validation_true) 
next() 
} 

Problema B

Puede utilizar el middleware de una manera que no siempre se necesita llamar a autenticar y validar que se denominan de forma automática. Pero eso puede llevar a un desastre, por ej. Su middleware se ejecutará en cada llamada, por lo que para SIGNUP/REGISTER no tiene sentido ejecutar la autenticación.

Con validar, a veces tendría que validar el correo electrónico, a veces el teléfono no. por lo que ambos no pueden estar de acuerdo.

Así que utilizarlos por separado en cada llamada me parece la mejor manera.

+0

Para A, lo que estaba buscando validando diferentes conjuntos de parámetros para diferentes rutas - validar (x), validar (x, y), validar (x, y, z). ¿Es posible pasar parámetros como este, o simplemente haría que el parámetro estableciera una matriz y la pasara como validate (req, res, desiredparams, next) ... – nflacco

+0

bueno, sí. Pero creo que debes hacer que las funciones SUB y pasarlas dentro de la función validate. Al igual que validate_email (req.body.email); o incluso validate_desired (parametros deseados), y para la ruta debe verificar los parametros de req, ** PS: asi es como lo hago. ** :) –

+0

ok, eso parece bastante razonable – nflacco

2

Puede usar express-validation para validar cuerpo, consulta, parámetros, encabezados y cookies de una solicitud. Responde con errores si falla alguna de las reglas de validación configuradas.

var validate = require('express-validation'), 
    Joi = require('joi'); 

app.post('/login', validate({ 
    body: { 
    email: Joi.string().email().required(), 
    password: Joi.string().regex(/[a-zA-Z0-9]{3,30}/).required() 
    } 
}), function(req, res){ 
    res.json(200); 
}); 

Esto verificará si los parámetros del cuerpo del correo electrónico y la contraseña coinciden con las reglas de validación.

Si la validación falla, responderá con el siguiente error.

{ 
    "status": 400, 
    "statusText": "Bad Request", 
    "errors": [ 
    { 
     "field": "password", 
     "location": "body", 
     "messages": [ 
     "the value of password is not allowed to be empty", 
     "the value of password must match the regular expression /[a-zA-Z0-9]{3,30}/" 
     ], 
     "types": [ "any.empty", "string.regex.base" ] 
    } 
    ] 
} 

También puede comprobar mi repo express-mongoose-es6-rest-api para la integración completa.

1

También podría usar una función de orden superior (función que devuelve una función). De este modo, pasar una matriz de parámetros específicos de punto final para verificar.

module.export = Class RequestValidator { 
    static validate(params) { 
    return function(req, res, next){ 
     for(const param of params) { 
     validateYourParams here... 
     if (validation fails) { 
     return next(new Error()); 
     } 
     } 
     next(); 
    } 
    } 
} 

y dentro de su routeDefinition ahora se puede llamar el middleware validación y pasar argumentos específicos de la ruta a la misma.

const RequestValidator = require('your-validation-middleware'); 
const controller = require('your-controller'); 

app.post('/path') 
    .RequestValidator.validate(
    [{ 
    name: 'paramName', 
    type: 'boolean' 
    }, 
    { 
    name: 'paramName2', 
    type: 'string' 
    } 
    ]) 
    .Controller.handleRequest; 
Cuestiones relacionadas