• No results found

What is module.exports?

By default, JavaScript doesn’t have a way to pass information between different files. mod-ule.exportsis Node’s way of fixing this problem.

You can think of module.exportsas a giant object for our application. When our application starts, thismodule.exportsobject looks like this:

1 module.exports = {};

As we start pulling things into our app withrequire(), everything is added to this object.

So now as we add that newconfig.jsfile withrequire(./config.js);, we have access to those variables since we passed them throughmodule.exports.

This is how we will be passing information to and from all of our files and we’ll see this in practice again when we create our routes files.

It is also important to note that many tutorials on the web will switch betweenmodule.exportsand exports. They mean the same thing and can be used interchangeably.

Routes

Just like our configuration variables, let’s move our routes into their own files. Create a folder called app/routes/and a file calledapp/routes/api.js.

When creating new files, we will have torequire()anything that is needed by that file. In our case, we will needbody-parser, ourUsermodel, ourconfigfile for thesecret, andjsonwebtokensince those were used in our routes.

We will also need app and express but we will be passing those into our routes since we want our application to use the sameappobject we create inserver.js. Let’s take a look at how we’ll structure our routes/api.jsfile that holds all of our API routes. Go into your existing ‘server.js’

file from chapter 10 and grab out all of the route code, starting at ‘var apiRouter = express.Router();’.

We will be wrapping this in our module.exports so that it can be passed between our javascript files.

Also take note of the changes to our variable superSecret and the packages we are including at the top.

1 var User = require('../models/user');

2 var jwt = require('jsonwebtoken');

3 var config = require('../../config');

4

5 // super secret for creating tokens 6 var superSecret = config.secret;

7

8 module.exports = function(app, express) { 9

10 var apiRouter = express.Router();

11

12 // route to authenticate a user (POST http://localhost:8080/api/authenticate)

MEAN Stack Application Structure 141 13 apiRouter.post('/authenticate', function(req, res) {

14 console.log(req.body.username);

15

16 // find the user

17 // select the password explicitly since mongoose is not returning it by defa\

18 ult

19 User.findOne({

20 username: req.body.username

21 }).select('password').exec(function(err, user) { 22

23 if (err) throw err;

24

25 // no user with that username was found 26 if (!user) {

27 res.json({

28 success: false,

29 message: 'Authentication failed. User not found.'

30 });

31 } else if (user) {

32

33 // check if password matches

34 var validPassword = user.comparePassword(req.body.password);

35 if (!validPassword) {

36 res.json({

37 success: false,

38 message: 'Authentication failed. Wrong password.'

39 });

40 } else {

41

42 // if user is found and password is right

43 // create a token

44 var token = jwt.sign(user, superSecret, { 45 expiresInMinutes: 1440 // expires in 24 hours

46 });

47

48 // return the information including token as JSON

49 res.json({

50 success: true,

51 message: 'Enjoy your token!',

52 token: token

53 });

54 }

55

61 // route middleware to verify a token 62 apiRouter.use(function(req, res, next) { 63 // do logging

64 console.log('Somebody just came to our app!');

65

66 // check header or url parameters or post parameters for token

67 var token = req.body.token || req.query.token || req.headers['x-access-token\

68 '];

69

70 // decode token 71 if (token) { 72

73 // verifies secret and checks exp

74 jwt.verify(token, superSecret, function(err, decoded) {

75 if (err) {

76 return res.json({ success: false, message: 'Failed to authenticate tok\

77 en.' });

78 } else {

79 // if everything is good, save to request for use in other routes 80 req.decoded = decoded;

81

82 next(); // make sure we go to the next routes and don't stop here

83 }

89 // return an HTTP response of 403 (access forbidden) and an error message

90 return res.status(403).send({

91 success: false,

92 message: 'No token provided.'

93 });

94

95 }

96

MEAN Stack Application Structure 143 97 });

98

99 // test route to make sure everything is working 100 // accessed at GET http://localhost:8080/api 101 apiRouter.get('/', function(req, res) {

102 res.json({ message: 'hooray! welcome to our api!' });

103 });

104

105 // on routes that end in /users

106 // ---107 apiRouter.route('/users')

108

109 // create a user (accessed at POST http://localhost:8080/users) 110 .post(function(req, res) {

111

112 var user = new User(); // create a new instance of the User model 113 user.name = req.body.name; // set the users name (comes from the requ\

114 est)

115 user.username = req.body.username; // set the users username (comes f\

116 rom the request)

117 user.password = req.body.password; // set the users password (comes f\

118 rom the request) 119

120 user.save(function(err) {

121 if (err) res.send(err);

122

123 // return a message

124 res.json({ message: 'User created!' });

125 });

126

127 })

128

129 // get all the users (accessed at GET http://localhost:8080/api/users) 130 .get(function(req, res) {

131 User.find(function(err, users) {

132 if (err) res.send(err);

133

134 // return the users

135 res.json(users);

136 });

137 });

138

139 // on routes that end in /users/:user_id

145 User.findById(req.params.user_id, function(err, user) {

146 if (err) res.send(err);

147

148 // return that user

149 res.json(user);

150 });

151 })

152

153 // update the user with this id 154 .put(function(req, res) {

155 User.findById(req.params.user_id, function(err, user) { 156

157 if (err) res.send(err);

158

159 // set the new user information if it exists in the request 160 if (req.body.name) user.name = req.body.name;

161 if (req.body.username) user.username = req.body.username;

162 if (req.body.password) user.password = req.body.password;

163

164 // save the user

165 user.save(function(err) {

166 if (err) res.send(err);

167

168 // return a message

169 res.json({ message: 'User updated!' });

170 });

171

172 });

173 })

174

175 // delete the user with this id 176 .delete(function(req, res) {

177 User.remove({

178 _id: req.params.user_id

179 }, function(err, user) {

180 if (err) res.send(err);

MEAN Stack Application Structure 145

181

182 res.json({ message: 'Successfully deleted' });

183 });

184 });

185

186 return apiRouter;

187 };

If you look carefully, you’ll see this doesn’t differ too much from how our code looked inserver.js. The main difference is that we are requiringconfig.jsand usingconfig.secret.

We are also passing back a function into module.exports and requiring that app and express are passed in. This is so we can use theexpress object to get an instance of express.Router();. Currently, we are not using theappobject, but it note that if you are not using the express.Router(), you could directly specify routes on theappobject as well.

We will thenreturn apiRouter;so that we can use it inserver.js.

Now that this file is created, we just need to call it inserver.js. This is where we can see just how clean our main file has become and how much easier it is to read than before.

These are the lines to use inserver.jswhen calling our newly created routes file:

1 // API ROUTES

---2 var apiRoutes = require('./app/routes/api')(app, express);

3 app.use('/api', apiRoutes);

If you didn’t do it earlier, go through and remove those routes and calls to packages that we moved into ourapi.jsfile. And that’s it! Now we have moved about 170 lines of code out of ourserver.js!

Related documents