Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express direct to the wrong endpoint in production but work perfectly on development

express direct to the wrong endpoint on the production environment but works fine on development. I had built my application using express for back-end and react for front-end and passport for authentication, Here now I'm facing issue with endpoint /auth/google. when I click the button, it should direct to express endpoint auth, but express directs to react app not found component.

simply my app does not hit endpoint auth/google rather render react page

here the codes

server.js

app.use('/auth', require('./router/auth')) // should direct here
app.use('/media', require('./router/media')) 
app.use('/admin', require('./router/admin')) 
app.use('/user', require('./router/user'))

const httpServer = http.createServer(app)

if (process.env.NODE_ENV === 'production') {
 app.use(favicon(path.join(__dirname, '../' + 'build', 'favicon.ico')))

 app.use(express.static(path.join(__dirname, '../' + 'build')));

 app.get("*", (req, res) => { // but always goes here
 res.sendFile(path.join(path.join(__dirname, '../' + 'build', 'index.html')));
  });
}

const PORT = 8080

httpServer.listen(PORT, () => {
 console.log('Server up at:' + PORT)
})

/router/auth.js

router.get('/google', passport.authenticate('google', { // and should hit this 
  scope: ['profile', 'email']
}))
router.get(
  '/google/callback',
  passport.authenticate('google'),
  (req, res) => {
    req.app.set('user', res.req.user)
    return res.redirect('/auth/sign')
  }
)

module.exports = router

passport.js

export default function (passport) {
  passport.serializeUser(function (user, done) {
    done(null, user)
  })

  passport.deserializeUser(function (user, done) {
    done(null, user)
  })

  // GOOGLE OAuth
  passport.use(
    new GoogleStrategy(
      {
        clientID: GOOGLE_CLIENT_ID,
        clientSecret: GOOGLE_CLIENT_SECRET,
        callbackURL: '/auth/google/callback'
      },
      function (_, __, profile, done) {
        profile = {
          ...profile,
          email: profile.emails && profile.emails[0].value,
          profileUrl: profile.photos && profile.photos[0].value
        }
        authUser(profile, done) // function for save user
      }
    )
  )
}

react app.js


 <Switch>
          <Route path="/" exact component={Main} />
          <Route path="/home" exact component={Home} />
          <Route path="/ad/:id" exact component={Ad} />
          <PrivateRoute path="/postad" exact component={createAd} />
          <PrivateRoute path="/ad/edit/:id" exact component={UpdateAd} />
          <Route path="/user/:id" exact component={User} />
          <PrivateRoute path="/setting" exact component={Setting} />
          <PublicRoute path="/sign" exact component={ProviderSign} />
          <Route path="*" exact={true} component={PageNotFound} /> // but render this
 </Switch>

TLDR

My was was also redirecting to react page when it was set "proxy": "http://localhost:8080", and After I found this http-proxy-middleware and setup proxy on the client src folder

const proxy = require("http-proxy-middleware");

module.exports = app => {
  app.use(proxy("/auth/google", { target: "http://localhost:8080/" }));
  app.use(proxy("/auth/facebook", { target: "http://localhost:8080/" }));
};

after this works fine when I start my node server on port 8080 and client on port 3000,

And this is my login page button to hit endpoint /auth/google

<Button className={classes.authBtn}> 
 <a className={classes.removeStyle} href="/auth/google">Google</a>     
</Button>
like image 460
U.A Avatar asked Nov 06 '22 10:11

U.A


1 Answers

A solution for me is to, create a routes.js file like:

const express = require("express");
const router = express.Router();

const authRouter = require('./router/auth');
const mediaRouter = require('./router/media');
const adminRouter = require('./router/admin');
const userRouter = require('./router/user');

router.get("/", function(req, res, next) {
  res.status(200).json({
    isSuccess: true,
    message: "Server is up and running!"
  });
});

app.use('/auth', authRouter); 
app.use('/media', mediaRouter); 
app.use('/admin', adminRouter); 
app.use('/user', userRouter);

router.get("*", (req, res) => {
  res.status(200).json({
    isSuccess: false,
    message: "Invalid address!"
  });
});

module.exports = router;

Modify your server.js file as:

const httpServer = http.createServer(app);
const indexRouter = require("./routes"); // your routes.js

app.use("/api", indexRouter);

if (process.env.NODE_ENV === 'production') {
 app.use(favicon(path.join(__dirname, '../' + 'build', 'favicon.ico')))

 app.use(express.static(path.join(__dirname, '../' + 'build')));

 app.get("*", (req, res) => { // but always goes here
 res.sendFile(path.join(path.join(__dirname, '../' + 'build', 'index.html')));
  });
}

const PORT = 8080;

httpServer.listen(PORT, () => {
 console.log('Server up at:' + PORT)
})

And finally modify your auth.js as:

router.get('/google', passport.authenticate('google', { // and should hit this 
  scope: ['profile', 'email']
}))
router.get(
  '/google/callback',
  passport.authenticate('google'),
  (req, res) => {
    req.app.set('user', res.req.user)
    return res.redirect('api/auth/sign') // Changed this endpoint
  }
)

module.exports = router

This approach separates your API and Front-end routes. Hope this works for you.

like image 162
Muhammad Zeeshan Avatar answered Nov 13 '22 19:11

Muhammad Zeeshan