Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GET request returns index.html doc instead of json data

After deploying my mern app to Heroku, the GET request on the home page ('http://localhost:8000/post/') is now returning index.html instead of json data from the request. I'm getting 200 status code but the response is html. However, it works fine locally.
All the other requests are working except this one. Whenever I think I've fixed it, Heroku displays the json data instead of the UI on this same route. I'm assuming that these issues are related.

How can I solve this? Thanks!

route/controller - list posts

router.get('/', (list)) 

exports.list = (req, res) => {
  const sort = { title: 1 };
  Post.find()
    .sort(sort)
    .then((posts) => res.json(posts))
    .catch((err) => res.status(400).json("Error: " + err));
};

server.js

require("dotenv").config();

// import routes
...
const app = express();

// connect db - first arg is url (specified in .env)
const url = process.env.MONGODB_URI 
mongoose.connect(url, {
  useNewUrlParser: true,
  useCreateIndex: true,
  useUnifiedTopology: true,
  useFindAndModify: false,
});
mongoose.connection
  .once("open", function () {
    console.log("DB Connected!");
  })
  .on("error", function (error) {
    console.log("Error is: ", error);
  });

// middlewares
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", '*');
  res.header("Access-Control-Allow-Credentials", true);
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
  next();
});

// middleware
...
//  app.use(express.static(path.join(__dirname, './client/build')))
app.use(authRoutes);
app.use(userRoutes);
app.use('/post', postRoutes);

if (process.env.NODE_ENV === "production") {
  app.use(express.static("client/build"));
}

app.get("/*", function (req, res) {
  res.sendFile(path.join(__dirname, "./client/build/index.html"));
});

const port = process.env.PORT || 80;

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

ListPosts.js

class ListPosts extends React.Component {
    state = {
        title: '',
        body: '',
        date: '',
        posts: []
    }

    componentDidMount = () => {
        this.getPosts()
    }

   getPosts = () => {
        axios.get(`${API}/post`)
        .then((response) => {
            const data = response.data
            this.setState({posts: [data]})
            console.log(data)
        })
        .catch((error) => {
            console.log(error)
        })
    }
     
    displayPosts = (posts) => {
        if (!posts.length) return null;
      posts.map((post, index) => (
            <div key={index}>
           ...
            </div>    
        ))
    }


    render() {
        return (
         <div>
           {this.displayPosts(this.state.posts)}
           </div>
        )
    }
}

export default ListPosts
like image 817
SK7 Avatar asked Oct 23 '20 08:10

SK7


People also ask

Why should I care if my API returns JSON?

If your API returns JSON, or some other form of pure data, it becomes much more useful. The existing app can still consume that data, and present it appropriately. Now, though, other things can use the API to access the same data.

How do I get JSON from a request body?

The json () method of the Request interface reads the request body and returns it as a promise that resolves with the result of parsing the body text as JSON. Note that despite the method being named json (), the result is not JSON but is instead the result of taking JSON as input and parsing it to produce a JavaScript object.

How to append JSON data dynamically to HTML elements?

First, we will fetch the JSON data by using the fetch API. This will return a promise with our JSON data. Then we will append the data dynamically by creating HTML elements on the fly. We will then append our JSON data to those elements. Getting JSON data from an API and display it on a web page is a common thing you will do quite often.

How to get JSON data from the response in JavaScript?

To get the JSON data from the response, we execute the json() function. The json() function also returns a promise. This is why we just return it and chain another then function. In the second then function we get the actual JSON data as a parameter. This data looks just like the data in our JSON file.


1 Answers

Your request 'http://localhost:8000/' matches two route handler

app.get("/*", function (req, res) {
  res.sendFile(path.join(__dirname, "./client/build/index.html"));
});

router.get('/', (list)) 

Since your client build route is placed above the list route it will always return the index.html because precedence matters in express when defining routes.

A good practice and solution is to always differentiate your api routes from the static ones by appending /api before all routes as below

app.use('api/auth', authRoutes);
app.use('api/post', postRoutes);
app.use('api/user', userRoutes);
like image 124
malong11 Avatar answered Sep 19 '22 13:09

malong11