GET request returns index.html doc instead of json data

℡╲_俬逩灬. 提交于 2020-12-05 11:50:26

问题


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

回答1:


As some of the answers already mentioned seperating your API and client routes and found the exact issue, I would like to just add a little bit of recommendations based on my experience with serving your react app using express. (Trick is to also add versioning)

app.use('/api/v1/auth', authRoutes);
app.use('/api/v1/user', userRoutes);
app.use('/api/v1/post', postRoutes);
if (process.env.NODE_ENV === 'production') {  
    app.use(express.static(path.join(__dirname, "client/build")));
    app.get("/*", (_, res) => {
     res.sendFile(path.join(__dirname, "client/build", "index.html"));
    });
}



回答2:


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);



回答3:


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

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

In server.js

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"));
});

....

app.use(authRoutes);
app.use(userRoutes);
app.use(postRoutes);

You need to update like this.

It's just sequence problem in express middlewares. You have updated middlewares about get method(/*). So it's always returning index.html instead of JSON.




回答4:


In your current implementation you have 2 app.get for the same path -> '/' So, express responds with the first one. Which right now is:

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

You can either, specify a different path

app.use("/post", postRoutes);

or rearrange the sequence.

app.use(authRoutes);
app.use(userRoutes);
app.use(postRoutes);

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

or change the controller

router.post('/' ...) // instead of router.get('/'...)

You need to specify the routes url or avoid two 'app.get' for the same route. If you want you can also change the controller from 'app.get' to 'app.post' and express will deem them different. But, if both are app.get for the same route, the first one will send the response and the second one will never be called.

What you can do is, first try to re-arrange the sequence. If it works and that is indeed the problem, don't stick with it as a solution. It's the wrong way to go about. Instead, give your routes a different url or change the controller from 'app.get' to 'app.post'



来源:https://stackoverflow.com/questions/64496815/get-request-returns-index-html-doc-instead-of-json-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!