繁体   English   中英

GET 请求返回 index.html doc 而不是 json 数据

[英]GET request returns index.html doc instead of json data

将我的 mern 应用程序部署到 Heroku 后,主页上的GET请求('http://localhost:8000/post/')现在从请求中返回index.html而不是json data 我收到200 status代码,但响应是html 但是,它在本地运行良好。
除了这个请求之外,所有其他请求都在工作。 每当我认为我已经修复它时,Heroku 会在同一条路线上显示 json 数据而不是 UI。 我假设这些问题是相关的。

我该如何解决这个问题? 谢谢!

路由/控制器 - 列出帖子

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

服务器.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

您的请求'http://localhost:8000/'匹配两个路由处理程序

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

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

由于您的客户端构建路由位于列表路由上方,因此它将始终返回 index.html,因为在定义路由时优先级在 express 中很重要。

一个好的做法和解决方案是始终通过在所有路由之前附加/api来区分你的 api 路由和静态路由,如下所示

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

在您当前的实现中,您有 2 个 app.get 用于相同的路径 -> '/' 所以,express 用第一个响应。 现在是:

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

您可以指定不同的路径

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

或重新排列顺序。

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

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

或者更换控制器

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

您需要指定路由 url 或避免为同一路由使用两个“app.get”。 如果您愿意,您还可以将控制器从“app.get”更改为“app.post”,express 会认为它们不同。 但是,如果两者都是相同路由的 app.get,第一个将发送响应,而第二个将永远不会被调用。

您可以做的是,首先尝试重新排列顺序。 如果它有效并且确实是问题所在,请不要坚持使用它作为解决方案。 这是错误的做法。 相反,给你的路由一个不同的 url 或将控制器从“app.get”更改为“app.post”

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;

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

你需要像这样更新。

这只是快递中间件中的序列问题。 您已更新有关 get 方法(/*)的中间件。 所以它总是返回 index.html 而不是 JSON。

由于一些答案已经提到将您的 API 和客户端路由分开并找到了确切的问题,因此我想根据我使用express为您的 React 应用程序提供服务的经验添加一些建议。 (技巧是还添加版本控制)

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

您可以更改const port = process.env.PORT || 80; const port = process.env.PORT || 80; 没有80端口的线路。 它对我const port = process.env.PORT;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM