很奇葩的Nodejs跳转问题
很奇葩的Nodejs跳转问题
app.del(’/:id’,function(req,res){
User.findById(req.params.id,function(err,doc){
if(!doc){
return next(new NotFound(‘document is not found’))
}
doc.remove(function(){
res.redirect(’/listuser’);
});
})
});
<% for(var i=0; i<doc.length; i++) { %>
<li>
<%= doc[i].id %>
<%= doc[i].username %>
<%= doc[i].password %>
<form method=‘post’ ,action=’/<%= doc[i].id %>’>
<input type=“submit” value=“del” />
</form>
</li>
<% } %>
Cannot POST /listuser ejs 为啥啊? app.post也不行。。。
很奇葩的Nodejs跳转问题
问题描述
在使用Node.js和EJS模板引擎时,我遇到了一个很奇怪的问题。当我在前端页面点击删除按钮后,虽然成功删除了数据库中的记录,但页面却无法正确跳转到用户列表页面(/listuser
)。相反,页面返回了一个 Cannot POST /listuser
的错误。
示例代码
首先来看一下后端的删除逻辑:
// app.js
const express = require('express');
const User = require('./models/User'); // 假设你有一个User模型
const app = express();
app.set('view engine', 'ejs');
app.del('/:id', function(req, res) {
User.findById(req.params.id, function(err, doc) {
if (!doc) {
return next(new NotFound('document is not found'));
}
doc.remove(function() {
res.redirect('/listuser');
});
});
});
app.get('/listuser', function(req, res) {
User.find({}, function(err, docs) {
if (err) throw err;
res.render('listuser', { doc: docs });
});
});
app.listen(3000);
然后是前端的HTML代码,用于展示用户列表并提供删除功能:
<!-- views/listuser.ejs -->
<ul>
<% for(var i=0; i<doc.length; i++) { %>
<li>
<%= doc[i].id %> - <%= doc[i].username %> - <%= doc[i].password %>
<form method='post' action='/<%= doc[i].id %>'>
<input type="submit" value="Delete" />
</form>
</li>
<% } %>
</ul>
问题分析
从上述代码可以看出,删除操作通过POST请求发送到服务器,而服务器实际处理的是DELETE请求。因此,当你提交表单时,客户端尝试向 /listuser
发送POST请求,但实际上并没有这样的路由来处理这个请求,所以返回了 Cannot POST /listuser
错误。
解决方案
- 修改前端表单的提交方式:将表单的提交方法改为DELETE,而不是POST。这可以通过在表单中添加一个隐藏字段来实现。
<form method='post' action='/<%= doc[i].id %>'>
<input type="hidden" name="_method" value="delete">
<input type="submit" value="Delete" />
</form>
- 更新后端路由处理:使用中间件来处理
_method
参数,并根据其值更改HTTP方法。
// app.js
const methodOverride = require('method-override');
app.use(methodOverride('_method'));
app.delete('/:id', function(req, res) {
User.findById(req.params.id, function(err, doc) {
if (!doc) {
return next(new NotFound('document is not found'));
}
doc.remove(function() {
res.redirect('/listuser');
});
});
});
通过以上修改,前端表单将正确地发送DELETE请求到后端,后端也会正确处理该请求,并重定向到用户列表页面。
有启用method-override
模块吗?
如果没有, 启用该模块,再加个
<input type="hidden" value="DELETE" name="_method">
可以删除了 不过没有执行跳转 显示Moved Temporarily. Redirecting to /listuser
<form method=‘post’ ,action=’/<%= doc[i].id%>/userdel’> app.del(’/:id/userdel’,function(req,res){ 这样则显示Cannot DELETE /listuser
根据你的描述,问题出在HTML表单提交的方式。你在EJS模板中使用了<form>
标签,并且其method
属性设置为POST
,而action
属性则指向了一个动态路径(如/123
),这会导致浏览器尝试通过POST方法向/123
发送请求,而不是/listuser
。
如果你想实现删除功能并重定向到用户列表页面,可以考虑以下方案:
- 使用
DELETE
方法模拟删除操作,可以通过隐藏字段或者改变form
的method
为DELETE
来实现。 - 修改服务器端代码,处理正确的HTTP方法。
示例代码
修改服务器端代码
const express = require('express');
const User = require('./models/User'); // 假设User模型已定义
const app = express();
app.delete('/:id', function (req, res, next) {
User.findById(req.params.id, function (err, doc) {
if (!doc) {
return next(new NotFound('document is not found'));
}
doc.remove(function () {
res.redirect('/listuser');
});
});
});
// 添加对DELETE请求的支持
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post('/:id/delete', function (req, res) {
req._parsedUrl = { pathname: '/delete' };
const id = req.params.id;
app._router.handle(req, res, function () {});
});
app.listen(3000, () => console.log('Server started on port 3000'));
修改客户端EJS模板
<% for (var i = 0; i < doc.length; i++) { %>
<li>
<%= doc[i].id %>
<%= doc[i].username %>
<%= doc[i].password %>
<form method="post" action="/<%= doc[i].id %>/delete">
<input type="hidden" name="_method" value="DELETE" />
<input type="submit" value="del" />
</form>
</li>
<% } %>
在这个例子中,我们通过添加一个隐藏的_method
字段,并将其值设置为DELETE
,模拟了DELETE请求。然后,在服务器端,我们通过检查请求体中的_method
字段来决定如何处理请求。
这样,当用户点击“del”按钮时,会发送一个POST请求到正确的路径,服务器端则会处理该请求并进行相应的删除操作。