我一直在研究Express 4应用程序(在前端有角度)但由于某种原因,req.body没有被填充。这是我的server.js:
// Import dependencies
var path = require('path');
var qs = require('querystring');
var async = require('async');
var bcrypt = require('bcryptjs');
var bodyParser = require('body-parser');
var express = require('express');
var logger = require('morgan');
var jwt = require('jwt-simple');
var moment = require('moment');
var mongoose = require('mongoose');
var request = require('request');
var SALT_WORK_FACTOR = 10;
// Config file
var config = require('./config');
// Initialize app
var app = express();
// App configuration
app.set('port', process.env.PORT || 8080);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, '/client')));
// User schema
var userSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true },
password: { type: String, select: false }
});
// Makes sure that our passwords are always hashed before saving to the database
// Refer to sessionBuddy's resources for more info on this
userSchema.pre('save', function(next) {
console.log("I'm in the pre.save() middleware");
var user = this;
// Only hash the password if its modified or new
if (!user.isModified('password')) return next();
// Generate salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password along with the salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
// overwrite the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
// Password verification for cleartext and hashed passwords
userSchema.methods.comparePassword = function(password, done) {
bcrypt.compare(password, this.password, function(err, isMatch) {
done(err, isMatch);
});
};
// User model
var User = mongoose.model('User', userSchema);
// Connect to the db
mongoose.connect(config.MONGO_URI);
mongoose.connection.on('error', function() {
console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
});
/*
|--------------------------------------------------------------------------
| Login Required Middleware
|--------------------------------------------------------------------------
*/
function ensureAuthenticated(req, res, next){
if(!(req.headers && req.headers.authorization)){
return res.status(400).send({ message: 'You did not provide a JSON Web Token in the authorization header.'});
}
// Decode the token
var header = req.headers.authorization.split(' ');
var token = header[1];
var payload = jwt.decode(token, config.TOKEN_SECRET);
var now = moment().unix();
// Check if the token is expired
if(now > payload.exp){
return res.status(401).send({ message: 'Token has expired. '});
}
// Check if the user still exists in the db
User.findById(payload.sub, function(err, user){
if(!user){
return res.status(400).send({ message: 'User no longer exists. '});
}
// Attach the "user" object to the "request" object (req)
// So now if we want to access current user's info in a protected route like
// /api/feed we can just access "req.user" object
// So basically every protected route like /api/feed or /api/media/:id
// needs to first call isAuthenticated() to get the user
// NOTE: please check the protected routes in "server.js" of sahat's Instagram tutorial
req.user = user;
next();
})
}
/*
|--------------------------------------------------------------------------
| Generate JWT Token
|--------------------------------------------------------------------------
*/
function createToken(user){
var payload = {
exp: moment().add(14, 'days').unix(),
iat: moment().unix(),
sub: user._id
};
return jwt.encode(payload, config.TOKEN_SECRET);
}
/*
|--------------------------------------------------------------------------
| Signup Route (/api/signup)
|--------------------------------------------------------------------------
*/
app.post('/auth/signup', function(req, res){
console.log("This is the email we recieve in /auth/signup ->", req.body.email);
// First make sure there are no accounts with same email already registered
User.findOne({ email: req.body.email }, function(err, existingUser){
// If found a user (with the same email)
if(existingUser){
console.log('Email already taken');
return res.status(409).send({ message: 'Email is already taken' });
}
// Make a user object
// NOTE: don't worry about hashing the password before saving here because
// we already have a pre.save() middleware on the userSchema that makes sure
// that all passwords are hashed before being inserted
var user = new User({
email: req.body.email,
password: req.body.password
});
// Now save the user in the db
// create and send a JWT token back along with the user
user.save(function(){
console.log("I'm in the user.save() function");
var token = createToken(user);
res.send({ token: token, user: user });
});
});
});
/*
|--------------------------------------------------------------------------
| Login Route (/api/login)
|--------------------------------------------------------------------------
*/
app.post('/auth/login', function(req, res){
// Check if the user exists
// we do "+password" to get the password field in the result of the query back
// We have to do this cos we did "select : false" for password earlier
console.log("This is the email here ->", req.body.email);
User.findOne({ email: req.body.email }, '+password', function(err, user){
// If user wasn't found
if(!user){
console.log('User not found');
return res.status(401).send({ message: { email: 'Incorrect email' } });
}
// Call the comparePassword() function of the userSchema to check if the passwords match
user.comparePassword(req.body.password, function(err, isMatch){
// Passwords didn't match
if(!isMatch){
console.log("Passwords didn't match");
return res.status(401).send({ message: 'Wrong email and/or password' });
}
// Passwords matched
// Send a JWT token back
var token = createToken(user);
res.send({ token: token });
})
})
});
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/client/index.html'));
});
// Start the server
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});

这是我的注册表单
<div class="container">
<br/>
<div class="row">
<div class="center-form panel">
<form method="post" ng-submit="signup()" name="signupForm">
<div class="panel-body">
<h2 class="text-center">Sign up</h2>
<!-- Email -->
<div class="form-group" ng-class="{ 'has-success' : signupForm.email.$valid && signupForm.email.$dirty, 'has-error' : signupForm.email.$invalid && signupForm.email.$dirty }">
<!-- Email input -->
<input class="form-control input-lg" type="email" id="email" name="email" ng-model="email" placeholder="Email" required autofocus>
<!-- Email ngmessage -->
<div class="help-block text-danger" ng-if="signupForm.email.$dirty" ng-messages="signupForm.email.$error">
<div ng-message="required">Sorry, email address is required</div>
<div ng-message="email">Sorry, the email address you entered is invalid</div>
</div>
</div>
<!-- Password -->
<div class="form-group" ng-class="{ 'has-success' : signupForm.password.$valid && signupForm.password.$dirty, 'has-error' : signupForm.password.$invalid && signupForm.password.$dirty }">
<!-- Password input -->
<input class="form-control input-lg" type="password" name="password" ng-model="password" placeholder="Password" required>
<!-- Password ngmessage -->
<div class="help-block text-danger" ng-if="signupForm.password.$dirty" ng-messages="signupForm.password.$error">
<div ng-message="required">Sorry, password is required.</div>
</div>
</div>
<!-- Confirm Password -->
<div class="form-group" ng-class="{ 'has-success' : signupForm.confirmPassword.$valid && signupForm.confirmPassword.$dirty, 'has-error' : signupForm.confirmPassword.$invalid && signupForm.confirmPassword.$dirty }">
<!-- Confirm Password input -->
<input class="form-control input-lg" type="password" name="confirmPassword" ng-model="confirmPassword" repeat-password="password" placeholder="Confirm Password" required>
<!-- Confirm Password ngmessage -->
<div class="help-block text-danger" ng-if="signupForm.confirmPassword.$dirty" ng-messages="signupForm.confirmPassword.$error">
<div ng-message="required">Sorry, you must confirm password.</div>
<div ng-message="repeat">Sorry, passwords do not match</div>
</div>
</div>
<!-- Button -->
<button type="submit" ng-disabled="signupForm.$invalid" class="btn btn-lg btn-block btn-primary">Create Account</button>
</div>
</form>
</div>
</div>
</div>
&#13;
这是我的注册控制器
angular.module('MyApp')
.controller('SignupCtrl', function($scope, $auth){
console.log("I'm in Signup controller");
console.log("This is the email I get in signup controller", $scope.email);
// get the "user" object from the view
var user = {
email : $scope.email,
password: $scope.password
};
console.log(user);
// signup function
$scope.signup = function(){
console.log("I'm in Signup controller");
console.log("This is the email I get in signup()", $scope.email);
// call the signup() function from the $auth service (Which is part of Satellizer)
$auth.signup(user)
.then(function(response){
console.log(response.data);
});
};
});
&#13;
在我通过输入电子邮件和密码运行注册表单后,我注意到在请求通过注册控制器之前,它具有电子邮件的值(请参见下图)
然而,在/ auth / signup路由中,req.body.email的值仍未定义(请参见下图)
我也尝试使用谷歌搜索/搜索stackoverflow,但还没有能够解决它。
感谢您的帮助!
编辑1:这是发布请求的正文
{
"log": {
"version": "1.2",
"creator": {
"name": "WebInspector",
"version": "537.36"
},
"pages": [],
"entries": [
{
"startedDateTime": "2015-02-18T07:33:14.106Z",
"time": 30.250072479248047,
"request": {
"method": "POST",
"url": "http://localhost:8080/auth/signup",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Origin",
"value": "http://localhost:8080"
},
{
"name": "Accept-Encoding",
"value": "gzip, deflate"
},
{
"name": "Host",
"value": "localhost:8080"
},
{
"name": "Accept-Language",
"value": "en-US,en;q=0.8"
},
{
"name": "User-Agent",
"value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"
},
{
"name": "Content-Type",
"value": "application/json;charset=UTF-8"
},
{
"name": "Accept",
"value": "application/json, text/plain, */*"
},
{
"name": "Referer",
"value": "http://localhost:8080/"
},
{
"name": "Connection",
"value": "keep-alive"
},
{
"name": "Content-Length",
"value": "2"
}
],
"queryString": [],
"cookies": [],
"headersSize": 448,
"bodySize": 2,
"postData": {
"mimeType": "application/json;charset=UTF-8",
"text": "{}"
}
},
"response": {
"status": 200,
"statusText": "OK",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Date",
"value": "Wed, 18 Feb 2015 07:33:14 GMT"
},
{
"name": "Connection",
"value": "keep-alive"
},
{
"name": "X-Powered-By",
"value": "Express"
},
{
"name": "Content-Length",
"value": "226"
},
{
"name": "Content-Type",
"value": "application/json; charset=utf-8"
}
],
"cookies": [],
"content": {
"size": 226,
"mimeType": "application/json",
"compression": 0
},
"redirectURL": "",
"headersSize": 171,
"bodySize": 226
},
"cache": {},
"timings": {
"blocked": 2.55699999979697,
"dns": -1,
"connect": -1,
"send": 0.11399999857531018,
"wait": 26.36900000288732,
"receive": 1.2100724779884473,
"ssl": -1
},
"connection": "274032"
}
]
}
}
&#13;
编辑2:这是使用firebug的req主体的另一个屏幕截图
编辑3:因为@Quest建议我在signup()函数之外初始化用户对象,这就是它发送空POST数据的原因。所以当我把它移到函数内部时(包括signup()和login()),它们现在都可以工作了。