4
votes

La requête GET renvoie un doc index.html au lieu des données json

Après avoir déployé mon application mern sur Heroku, la requête GET sur la page d'accueil ('http://localhost:8000/post/') renvoie maintenant index.html au lieu des json data de la requête. J'obtiens un code d' 200 status mais la réponse est html . Cependant, cela fonctionne bien localement.
Toutes les autres demandes fonctionnent sauf celle-ci. Chaque fois que je pense que je l'ai corrigé, Heroku affiche les données json au lieu de l'interface utilisateur sur cette même route. Je suppose que ces problèmes sont liés.

Comment puis-je résoudre ça? Merci!

route / controller - liste des messages

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

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

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


3 commentaires

Où est votre API? On dirait que vous envoyez une requête axios au même serveur qui sert le code React.


L'API est sur localhost: 8000 et donc l'application react est sur le port 8001 @Dilshan


Pouvez-vous ajouter l'objet de requête axios


4 Réponses :


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

3 commentaires

Merci pour votre réponse. J'ai essayé cela mais malheureusement, il répond toujours avec index.html. @NattawutPornpetcharat


module.exports = routeur; Avez-vous mis à jour comme ça sur l'itinéraire? Pouvez-vous publier plus de code sur postRoutes?


Oui, j'avais déjà une déclaration d'exportation dans le fichier d'itinéraire. Je ne l'avais simplement pas ajouté à mon code sur SO. Tous mes autres itinéraires fonctionnent bien, c'est juste celui-ci qui renvoie du html. @NattawutPornpetcharat



2
votes

Dans votre implémentation actuelle, vous avez 2 app.get pour le même chemin -> '/' Donc, express répond avec le premier. Ce qui est actuellement:

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

Vous pouvez soit spécifier un chemin différent

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

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

ou réorganisez la séquence.

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

ou changer de contrôleur

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

Vous devez spécifier l'URL des routes ou éviter deux 'app.get' pour la même route. Si vous le souhaitez, vous pouvez également changer le contrôleur de 'app.get' à 'app.post' et express les jugera différents. Mais, si les deux sont app.get pour la même route, le premier enverra la réponse et le second ne sera jamais appelé.

Ce que vous pouvez faire, c'est d'abord essayer de réorganiser la séquence. Si cela fonctionne et que c'est effectivement le problème, ne vous en tenez pas à cela comme solution. C'est la mauvaise façon de procéder. Au lieu de cela, donnez à vos routes une URL différente ou changez le contrôleur de 'app.get' à 'app.post'


0 commentaires

7
votes

Votre requête 'http://localhost:8000/' correspond à deux gestionnaires de route

app.use('api/auth', authRoutes);
app.use('api/post', postRoutes);
app.use('api/user', userRoutes);

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

Puisque votre route de construction client est placée au-dessus de la route de liste , elle renverra toujours l'index.html car la priorité est importante dans express lors de la définition des routes.

Une bonne pratique et une solution consiste à toujours différencier vos routes API des routes statiques en ajoutant /api avant toutes les routes comme ci-dessous

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


0 commentaires

1
votes

Comme certaines des réponses ont déjà mentionné la séparation de votre API et des routes client et ont trouvé le problème exact, je voudrais simplement ajouter quelques recommandations basées sur mon expérience avec la diffusion de votre application React en utilisant express . (L'astuce consiste également à ajouter le contrôle de version)

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


0 commentaires