-3

It appears some route middleware is running before index.js, which is crashing my application because the order of execution prevents me from loading my dotenv file on time.

I would like to load my dotenv file before everything in order to make sure that all modules that require it will have access to it.

However, while debugging this issue, I noticed that a console.log at the top of the app entry point still doesn't log first.

Folder structure:

src
------index.js
middleware
------auth.js
routes
------auth.route.js
------index.js
.env

Code that logs first middleware/auth.js:

import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'

module.exports = function() {
  console.log('this prints first with undefined', process.env.JWT_SECRET) <-------

which gets called in auth.route.js

import auth from '../middleware/auth'

const userRouter = express.Router()

userRouter.get('/dashboard', auth().authenticate(), function(req, res) {
  res.send('Authenticated, user id is: ' + req.user.id)
})

index.js file:

console.log("this prints second");                        <---------
(...)
import routes from './routes'
import express from 'express'
import auth from './middleware/auth'

require('dotenv').config({ silent: process.env.NODE_ENV === 'production' })

const app = express();
(...)
app.use('/api', routes);
softcode
  • 4,358
  • 12
  • 41
  • 68
  • you haven't specified what the entry point of this server is. – Kevin B Feb 16 '17 at 21:26
  • It's `index.js` @KevinB – softcode Feb 16 '17 at 21:27
  • Right. so, you imported auth from middleware/auth, so middelware/auth runs so that you can import from it, then you rquire dotenv. makes sense. you should in fact be seeing what you are seeing. – Kevin B Feb 16 '17 at 21:28
  • @KevinB I have tried switching the order of import between dotenv and middleware/auth, which didn't change anything. The logs print in the same order – softcode Feb 16 '17 at 21:30
  • http://stackoverflow.com/questions/29329662/are-es6-module-imports-hoisted – Kevin B Feb 16 '17 at 21:31
  • With what you've given so far, it shouldn't be calling auth's exported functino before you log in index.js, but i suspect you're importing something else that does call it sooner than that, such as auth.route.js – Kevin B Feb 16 '17 at 21:37
  • @KevinB edited question with updates from link you sent – softcode Feb 16 '17 at 21:38
  • Right, import vs require both work the same with regard to what i was pointing out – Kevin B Feb 16 '17 at 21:39
  • @KevinB snap ok... Not sure where to go from here – softcode Feb 16 '17 at 21:40
  • How is auth.route.js related to this code? what brings it in? That file when required or imported will immediately call `auth()`, which i suspect is where the problem lies. – Kevin B Feb 16 '17 at 21:40
  • @KevinB edited with auth.route.js – softcode Feb 16 '17 at 21:42
  • Yup. When you import routes, which likely imports auth.route.js, you're importing `auth` and then calling it, thus causing your problem. though... i'm not sure what to suggest to fix that. – Kevin B Feb 16 '17 at 21:44

1 Answers1

0

It's not clear from the code fragments in your question where the problem, because I think you've omitted the place where you import the auth.route.js module.

The answer that follows assumes that you actually import auth.route.js in the index.js file, probably before importing middleware/auth (which isn't actually used in the code fragment you posted). So, based on that assumption, here's what's probably happening:

The thing to keep in mind is that code in a module is executed when it is imported. This doesn't affect middleware/auth at first, since all it does is declare a function. But it does affect auth.route.js - look at what that module does:

It imports the auth function from middleware/auth module, which calls the userRouter.get() function. One of the arguments to that function is a call to the auth() function.

If you're importing auth.route.js in your code (and I suspect you are), then that's where the auth function is getting called prematurely.

Now, how to fix this? It's actually pretty easy: the auth.route.js file should export a function which is called to initialize the routes when you're ready, like this:

auth.route.js

import auth from '../middleware/auth'

const userRouter = express.Router()

export default () => {
  userRouter.get('/dashboard', auth().authenticate(), function(req, res) {
    res.send('Authenticated, user id is: ' + req.user.id)
  })

  return userRouter;
}

And when you're ready to initialize the routes (ie. when everything else is set up).

import getRouter from './modules/auth.route.js';

app.use('/api', getRouter());
Kryten
  • 15,230
  • 6
  • 45
  • 68
  • Yup that works. However it is probably easier to modify my authenticate function itself rather than all protected routes – softcode Feb 16 '17 at 21:58