GET 请求 returns index.html 文档而不是 json 数据
GET request returns index.html doc instead of json data
将我的 mern 应用程序部署到 Heroku 后,主页 ('http://localhost:8000/post/')
上的 GET
请求现在从请求中返回 index.html
而不是 json data
。我收到 200 status
代码,但响应是 html
。但是,它在本地运行良好。
除此请求外,所有其他请求均正常运行。
每当我认为我已经修复它时,Heroku 都会在同一条路线上显示 json 数据而不是 UI 。我假设这些问题是相关的。
我该如何解决这个问题?谢谢!
route/controller - 列出帖子
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
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);
你需要这样更新。
这只是 express 中间件中的顺序问题。您已更新有关 get 方法 (/*) 的中间件。所以它总是返回 index.html 而不是 JSON.
在您当前的实现中,同一路径有 2 个 app.get -> '/'
所以,快递用第一个回应。现在是:
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,则第一个将发送响应而第二个将永远不会被调用。
你可以做的是,首先尝试 re-arrange 序列。如果它有效并且确实是问题所在,请不要坚持将其作为解决方案。这是错误的做法。相反,给你的路线一个不同的 url 或将控制器从 'app.get' 更改为 'app.post'
您的请求'http://localhost:8000/'
匹配两个路由处理程序
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
router.get('/', (list))
由于您的 client build 路由位于 list 路由上方,因此它将始终 return index.html因为定义路由时优先级很重要。
一个好的做法和解决方案是始终通过在所有路由之前附加 /api
来区分您的 api 路由和静态路由
app.use('api/auth', authRoutes);
app.use('api/post', postRoutes);
app.use('api/user', userRoutes);
由于一些答案已经提到将您的 API 和客户端路由分开并找到了确切的问题,我想根据我使用 express
。 (技巧是还添加版本控制)
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;
没有 80 端口的线路。它对我有用 const port = process.env.PORT;
将我的 mern 应用程序部署到 Heroku 后,主页 ('http://localhost:8000/post/')
上的 GET
请求现在从请求中返回 index.html
而不是 json data
。我收到 200 status
代码,但响应是 html
。但是,它在本地运行良好。
除此请求外,所有其他请求均正常运行。
每当我认为我已经修复它时,Heroku 都会在同一条路线上显示 json 数据而不是 UI 。我假设这些问题是相关的。
我该如何解决这个问题?谢谢!
route/controller - 列出帖子
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
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);
你需要这样更新。
这只是 express 中间件中的顺序问题。您已更新有关 get 方法 (/*) 的中间件。所以它总是返回 index.html 而不是 JSON.
在您当前的实现中,同一路径有 2 个 app.get -> '/' 所以,快递用第一个回应。现在是:
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,则第一个将发送响应而第二个将永远不会被调用。
你可以做的是,首先尝试 re-arrange 序列。如果它有效并且确实是问题所在,请不要坚持将其作为解决方案。这是错误的做法。相反,给你的路线一个不同的 url 或将控制器从 'app.get' 更改为 'app.post'
您的请求'http://localhost:8000/'
匹配两个路由处理程序
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
router.get('/', (list))
由于您的 client build 路由位于 list 路由上方,因此它将始终 return index.html因为定义路由时优先级很重要。
一个好的做法和解决方案是始终通过在所有路由之前附加 /api
来区分您的 api 路由和静态路由
app.use('api/auth', authRoutes);
app.use('api/post', postRoutes);
app.use('api/user', userRoutes);
由于一些答案已经提到将您的 API 和客户端路由分开并找到了确切的问题,我想根据我使用 express
。 (技巧是还添加版本控制)
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;
没有 80 端口的线路。它对我有用 const port = process.env.PORT;