我无法将req.params.id的输入用于其他文件

时间:2017-04-29 05:12:59

标签: javascript node.js mongodb express middleware

我正在构建一个 REST API ,它允许我们为企业创建用户和一些优惠券。为了简单起见,我只定义了几条路线。 我的主要文件是 coupon-api.js 。我已在此文件中定义了我的路线以及在不同文件中执行所需的功能,即 coupons.js用于优惠券功能,users.js用于用户功能。我的架构在两个单独的文件中定义,即 coupon.js和user.js

下面的代码第一次完美运行并返回一个空数组。

app.get('/ coupons',coupons.getAllCoupons);

接下来通过此代码,我可以使用POSTMAN创建优惠券      app.post('/ coupons',coupons.createCoupon);

现在,如果我这样做 app.get('/ coupons',coupons.getAllCoupons);
我可以使用定义的ID获取新创建的优惠券。 我面临的问题是当我去以下地址时 localhost:3000 /优惠券/(我获得新优惠券的身份)
它返回500内部服务器错误。主要问题是应该存储在req.params.id中的我的ID无法在定义所有需要执行的功能的文件中访问,即coupons.js文件。

我的所有代码都在下面定义。 主要文件 - coupon-api.js

const express = require('express');
const path = require('path');
const logger = require('morgan');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');

const config = require('./models/config');

const users = require('./controllers/users');
const coupons = require('./controllers/coupons');
var app = express();

mongoose.connect('localhost:5000');

if(app.get('env') === 'development') var dev = true;

// log if in dev mode
if(dev) app.use(logger('dev'));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended : false }));

//====================================
// More Middleware
//====================================

app.param('id' , function(req,res,next,id) {
	if(!id.match(/^[0-9a-fA-F]{24}$/))
		return res.status(400).send("invalid ID"); // using a regular expression to 
						           //discard certain input
});

//=====================================
// Routes
//=====================================

app.get('/users' , users.getUsers);
app.get('/users/:id' , users.getUserById);
app.post('/users' , users.createUser);
app.delete('/users/:id' , users.deleteUserById);
app.put('/users/:id' , users.updateUser);

app.get('/coupons' , coupons.getAllCoupons);
app.get('/coupons/:id' , coupons.getCouponById);
app.post('/coupons' , coupons.createCoupon);
app.put('/coupons/:id' , coupons.updateCoupon);
app.delete('/coupons/:id' , coupons.deleteCouponById);

//Handle 404
app.use(function(req,res,next) {
	var err = new Error('Not Found');
	err.status = 404;
	next(err);
});

//our defined error handler just for testing purposes
app.use(function(err,req,res,next) {
	console.log('oops');
	next(err);
});

//development error handler
if(dev) {
	app.use(function(err,req,res,next) {
		console.log(err);
		res.status(err.status || 500).send();
	});
}

//production error handler
app.use(function(err,req,res,next) {
	res.status(err.status || 500).send();
});

var server = app.listen(config.port);
console.log("Listening at http://localhost:%s in %s mode" , server.address().port,app.get('env'));

module.exports =app;

定义路线功能的控制器文件:coupons.js

const Coupon = require('../models/schemas/coupon');

module.exports.createCoupon = function(req,res,next) {       	
	var newCoupon = new Coupon(req.body);
	newCoupon.save(function(err,coupon) {
		if(err) return next(err);
		return res.status(200).send("OK");
	});
}

module.exports.getAllCoupons = function(req,res,next) {
	Coupon.find({} , function(err , coupons) {
		if(err) return next(err);
		return res.json(coupons);
	});
}

module.exports.getCouponById = function(req,res,next) {
	Coupon.findById(req.params.id , function(err, coupon) {
		if(err) return next(err);
		if(!coupon) return res.status(404).send("No coupon with that ID");
		return  res.json(coupon);
	});
};

module.exports.updateCoupon = function(req,res,next) {
	Coupon.findOneAndUpdate(req.params.id , req.body , {new:true} , function(err , coupon) {
		if(err) return next(err);
		if(!coupon) return res.status(404).send("No coupon with that ID");
		return res.json(coupon);
	});
}

module.exports.deleteCouponById = function(req,res,next) {
	Coupon.findOneAndRemove(req.params.id , function(err,coupon) {
		if(err) return next(err);
		if(!coupon) return res.status(404).send("No coupon with that ID");
		return res.status(200).send("OK");
	});
}

	 
module.exports.getActiveCoupons = function(req,res) {
	Coupon.find( {
		$and: [
			{ startDate : { $lt : now } },
			{ approvedDate: { $exists : true } },
			{ $or: [
				{ endDate : { $gt: now } },
				{ endDate : { $exists : false } }
			
			]}
		]		
	} , function(err,coupons) {
		if(err) return next(err);
		return res.json(coupons);
 
	});
}

module.exports.getUnapprovedCoupons = function(req, res, next) {
	Coupon.find({approvedDate : {$exists : false }}, function(err, coupons) {
		if(err) return next(err)
		return res.json(coupons);
	});
}

module.exports.approveCoupon = function(req, res, next) {
	Coupon.finOneAndUpdate(req.params.id , { approvedDate : new Date() } , {new : true} , function(err, coupon) {
		if(err) return next(err);
		if(!coupon) return res.status(404).send("No coupon with that ID");
		return res.json(coupon);
	});
}

用于定义用户路线功能的控制器文件

const User = require('../models/schemas/user');
	
module.exports.createUser = function(req,res) {
	
	var data = {
		firstName : req.body.firstName,
		lastName : req.body.lastName,
		email : req.body.email,
		password : req.body.password,
		createdDate: new Date()
	};
	
	var newUser = new User(data);
	
	//insert or store  user using mongoose	
	newUser.save(function(err,user) {
		return res.send('it worked');
	});
		
}



module.exports.getUsers = function(req, res, next) {
	User.find( {} , function(err , users) {
		if(err) return next(err)
		return res.json(users);		
	});
}


module.exports.getUserById = function(req,res,next) {
	User.findById(req.params.id , function(err , user) {
		if(err) return next(err);	
		if(!user) return res.status(404).send('user not found');
		return res.json(user);
	
	});
}

module.exports.updateUser = function(req,res,next) {
	User.findOneAndUpdate(req.params.id , req.body , { new:true } , function(err, user) {
	if(err) return next(err);
	if(!user) return res.status(404).send("No user with that ID");
	return res.json(user);	
	});	

}

module.exports.deleteUserById = function(req,res,next) {
	User.findOneAndRemove(req.params.id , function(err , user) {
		if(err) 
			return next(err);
		if(!user) 
			return res.status(404).send("No user with that ID");
		return res.status(200).send('OK');
	});

}

优惠券的架构代码

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

var couponSchema = new Schema({
        name: {type: String, required: true, trim: true},
        url: {type: String, required: true, trim: true},
        companyName: {type: String, required: true, trim: true},
        startDate: {type: Date, default: Date.now, index: true},
        endDate: {type: Date, index: true},
        tags: [Number],
        clicks: {type: [Date], default: []},
        views: {type: [Date], default: []},
        redeemed: {type: [Date], default: []},
        postedBy: Schema.ObjectId, //ref: 'User', required: true},
        approvedDate: Date
    },
    {
        toObject: { getters: true },
	//change name of mongoose default timestamps
        timestamps: {
            createdAt: 'createdDate',
            updatedAt: 'updatedDate'
        }
    }
);

couponSchema.pre('save', function(callback) {
    // ensure url starts with http://, https://, ftp://
    if (this.url && !(/^((https?)|(ftp)):\/\/.+/.test(this.url)))
        this.url = 'http://' + this.url;
    // update startDate on approval
    if (this.isModified('approvedDate') && this.approvedDate > this.startDate)
        this.startDate = this.approvedDate;

    callback();
});

var Coupon = mongoose.model('Coupon', couponSchema);

module.exports = Coupon;

我的用户架构代码

const mongoose = require('mongoose');
const Schema = mongoose.Schema;


var userSchema = new Schema({
        firstName: {type: String, trim: true},
        lastName: {type: String, trim: true},
        classYear: Number,
        email: {type: String, unique: true, sparse: true, trim: true},
        phone: {type: String, unique: true, sparse: true},
        phoneProvider: {type: String, trim: true},
        interests: [Number],
        isAdmin: {type: Boolean, index: true},
        isSuperAdmin: {type: Boolean, index: true},
        hash: String,
        companyName: {type: String, trim: true},
        token: String,
    },
    {
        toObject: { getters: true },
        timestamps: {
            createdAt: 'createdDate',
            updatedAt: 'updatedDate'
        },
    }
);

//hooks defined now
// hash if admin, ensure phone and provider if not
userSchema.pre('save', function(callback) {
    if (this.isAdmin || this.isSuperAdmin) {
        if (!this.email)
            return callback(new Error('Missing email'));
        if (!this.hash)
            return callback(new Error('Missing password'));
        if (!this.companyName)
            return callback(new Error('Missing companyName'));
	
	//TODO hash
       }

    else {
        if (!this.phone)
            return callback(new Error('Missing phone'));
        if (!this.phoneProvider)
            return callback(new Error('Missing phoneProvider'));
    }

    // validate phone
    if (this.phone) {
        if (typeof this.phone !== 'string')
            return callback(new Error('Invalid phone'));
        var phone = '';
        for (var i = 0; i < this.phone.length; i++) {
            if (!isNaN(this.phone[i]))
                phone += this.phone[i];
        }
        if (phone.length !== 10)
            return callback(new Error('Invalid phone'));
        this.phone = phone;
    }

    callback();
});

// create full name
userSchema.virtual('name').get(function() {
    var name = "";
    if (this.firstName) {
        name = this.firstName;
        if (this.lastName) name += ' ' + this.lastName;
    } else if (this.lastName) name = this.lastName;
    return name;
});

// methods for validating password
userSchema.methods.comparePassword = function(pw, callback) {
	bcrypt.compare(pw, this.hash, function(err, isMatch) {
		if (err) return callback(err);
		callback(null, isMatch);
	});
};

var User = mongoose.model('User', userSchema);

module.exports = User;

1 个答案:

答案 0 :(得分:0)

我认为问题出在您的中间件app.param()中。您应该调用next以使程序流继续到包含名为id的参数的路由。您可以尝试以下。

app.param('id' , function(req, res, next, id) {
    if(!id.match(/^[0-9a-fA-F]{24}$/)){
        return res.status(400).send("invalid ID"); 
    } else {
        next();
    }
});