I have been working on an Express 4 app (with angular on the frontend) but for some reason req.body is not being populated. Here's my 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'));
});
and here's my signup form
<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>
and here's my signup controller
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);
});
};
});
After I run the signup form by entering an email and a password, I noticed that till the request goes through the signup controller, it has the value of the email (please see the image below)
However the value of req.body.email is still undefined in the /auth/signup route (pl see the image below)
I have tried googling/ searching on stackoverflow as well but haven't been able to figure it out yet.
Thanks for your help!
EDIT 1: Here's the body of the post request
{
"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"
}
]
}
}
EDIT 2: Here's another screenshot of the req body using firebug
EDIT 3: So as @Quest suggested I was initializing user object outside signup() function thats why it was sending empty POST data. So when I moved it inside the function (both signup() and login()), they work now.
Aucun commentaire:
Enregistrer un commentaire