You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Node、Express、Mongoose时,DELETE删除功能失效但GET可用的原因与解决

问题

我正在开发一个CRUD项目,使用MongoDB、Express和Node.js实现根据ID删除条目。原删除功能用GET路由可以正常工作:

router.get('/delete/:id', async (req, res) => {
    try {
        const topic = await Topic.findById(req.params.id)
        await Topic.remove({ _id: req.params.id })
        res.redirect('/dashboard')
    } catch (error) {
       console.log(error) 
    }    
})

对应的EJS代码:

<div class="modifyTopic">
    <a href="/edit/<% topic._id %>"><i class="fas fa-edit fa-2x"></i></a>
    <a href="/delete/<%= topic._id %>"><i class="fas fa-trash fa-2x"></i></a>
</div>

但把路由改成DELETE方法后:

router.delete('/delete/:id', async (req, res) => {
    try {
        const topic = await Topic.findById(req.params.id)
        await Topic.remove({ _id: req.params.id })
        res.redirect('/dashboard')
    } catch (error) {
       console.log(error) 
    }    
})

功能失效,浏览器提示Cannot GET /delete/62def4aae6c2c1914cfa145fer3。请问:

  1. 为何会出现这种情况?
  2. 是否应该使用DELETE方法?
  3. 如何让删除功能通过DELETE方法正常工作?

解答

一、为什么改成DELETE路由后失效?

浏览器里的<a>标签默认会发送GET请求,但你把路由改成了DELETE方法,此时服务器上没有匹配该路径的GET路由,自然会返回Cannot GET错误。核心原因是请求方法和路由定义的方法不匹配。

二、是否应该使用DELETE方法?

必须用。按照RESTful API规范,删除资源的操作就该对应DELETE方法,用GET删资源存在诸多问题:

  • 不符合HTTP语义,GET本来是用来获取资源的;
  • 容易被爬虫、浏览器预加载误触发,导致数据意外删除;
  • 无法通过HTTP方法区分操作类型,不利于接口的维护和扩展。

三、实现DELETE方法删除的两种方案

方案1:用表单+method-override中间件(传统后端渲染方案)

HTML表单默认只支持GET和POST,所以需要借助method-override中间件把POST请求转换成DELETE:

  1. 安装并配置中间件
    先安装依赖:
    npm install method-override
    
    在Express入口文件(比如app.js)里添加配置:
    const methodOverride = require('method-override');
    // 用表单字段指定真实请求方法
    app.use(methodOverride('_method'));
    
  2. 修改EJS代码,把a标签换成表单
    把删除按钮的a标签改成表单提交:
    <div class="modifyTopic">
        <a href="/edit/<%= topic._id %>"><i class="fas fa-edit fa-2x"></i></a>
        <form action="/delete/<%= topic._id %>" method="POST" style="display: inline; margin: 0;">
            <input type="hidden" name="_method" value="DELETE">
            <button type="submit" style="border: none; background: transparent; padding: 0; cursor: pointer;">
                <i class="fas fa-trash fa-2x"></i>
            </button>
        </form>
    </div>
    
  3. 优化路由代码
    Topic.remove()已被废弃,推荐用更简洁的findByIdAndDelete:
    router.delete('/delete/:id', async (req, res) => {
        try {
            await Topic.findByIdAndDelete(req.params.id);
            res.redirect('/dashboard');
        } catch (error) {
            console.error(error);
            res.status(500).send('删除失败');
        }    
    })
    

方案2:用AJAX发送DELETE请求(动态交互场景)

保留a标签,通过JavaScript阻止默认跳转,用fetch发送DELETE请求:

  1. 修改EJS代码,给删除按钮加类标识
    <div class="modifyTopic">
        <a href="/edit/<%= topic._id %>"><i class="fas fa-edit fa-2x"></i></a>
        <a href="/delete/<%= topic._id %>" class="delete-btn"><i class="fas fa-trash fa-2x"></i></a>
    </div>
    
  2. 添加前端JS逻辑
    在页面底部或独立JS文件中添加:
    document.querySelectorAll('.delete-btn').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            e.preventDefault(); // 阻止默认GET跳转
            const deleteUrl = e.currentTarget.href;
            
            if (confirm('确定要删除这条记录吗?')) {
                try {
                    const response = await fetch(deleteUrl, { method: 'DELETE' });
                    if (response.ok) {
                        window.location.href = '/dashboard'; // 删除成功后跳转
                    } else {
                        alert('删除失败,请重试');
                    }
                } catch (err) {
                    console.error(err);
                    alert('删除请求出错');
                }
            }
        });
    });
    
  3. 路由代码保持不变(同样建议用findByIdAndDelete优化)

内容的提问来源于stack exchange,提问作者aquile hollins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 09:06:21