Mucahid Yazar
Mucahid Yazar

Reputation: 13

express.json() doens't work on production

I have a NodeJS and React project. I am having a problem. I didnt understand what the problems are. First I want to show you what my problem is.

on localhost. I want like this on heroku but it returns me as the next one enter image description here

My problem's photo:

enter image description here

As you see on the photo there is an html file in my user object on Heroku deployment.

But when I start my project on localhost the user has an object that is coming from my mongo database. Express.json() is catching and working correctly on localhost but it doesnt work on Heroku. Why does it happen? What is my problem?

Here is my server.js file :

const express = require("express");
const path = require("path");
const app = express();
const connectDB = require("./config/db");
const PORT = process.env.PORT || 5000;

connectDB();
app.use(express.json());

app.use(express.json({ extended: false }));
app.use(express.static("client/build"));

if (process.env.NODE_ENV === "production") {
  app.get("*", (req, res) => {
    res.sendFile(path.join(__dirname, "client", "build", "index.html"));
  });
}

app.use("/", require("./routes/quizRoute"));
app.use("/users", require("./routes/userRoute"));
app.use("/auth", require("./routes/authRoute"));

app.listen(PORT, () => {
  console.log("Server is started on the port " + PORT);
});

Client Side request

//SET AUTH WORK
import axios from "axios";

const setAuthToken = token => {
  if (token) {
    axios.defaults.headers.common["x-auth-token"] = token;
  } else {
    delete axios.dafaults.header.common["x-auth-token"];
  }
};

export default setAuthToken;

//LOAD USER

const loadUser = async () => {
    if (localStorage.token) {
      setAuthToken(localStorage.token);
    }
    try {
      const res = await axios.get("/auth");
      dispatch({ type: USER_LOADED, payload: res.data });
    } catch (err) {
      dispatch({
        type: AUTH_ERROR,
        payload:
          "AUTH_ERROR: Token dogrulanamadi veya /auth'a GET isteginde bir sorun var"
      });
    }
  };

enter code here

Upvotes: 0

Views: 140

Answers (1)

Tunmise Ogunniyi
Tunmise Ogunniyi

Reputation: 2573

Why you are having the issue:  
I believe your bundler sets the NODE_ENV value to production when it builds for the deploy environments i.e Heroku. So you are having this issue because of the catch-all route that sends back your client index.html on every get request:

if (process.env.NODE_ENV === "production") {
  app.get("*", (req, res) => {
    res.sendFile(path.join(__dirname, "client", "build", "index.html"));
  });
} 

Consequently, when you make the get request to the /auth route from your client app, the request gets intercepted by this catch-all route handler before getting to the expected route handler. I'm pretty certain you would get back that HTML string whenever you make any get request to your server, not just the for /auth

The solution:  
The easy fix for this would be for you to move the catch-all route below your API routes like this:

app.use("/", require("./routes/quizRoute"));
app.use("/users", require("./routes/userRoute"));
app.use("/auth", require("./routes/authRoute"));

// Every other API or similar routes should be before this catch-all
if (process.env.NODE_ENV === "production") {
  app.get("*", (req, res) => {
    res.sendFile(path.join(__dirname, "client", "build", "index.html"));
  });
}

Upvotes: 1

Related Questions