Express 无法 PUT/DELETE 方法。出了啥问题?

Posted

技术标签:

【中文标题】Express 无法 PUT/DELETE 方法。出了啥问题?【英文标题】:Express cannot PUT/DELETE method. What is going wrong?Express 无法 PUT/DELETE 方法。出了什么问题? 【发布时间】:2013-02-18 02:36:57 【问题描述】:

好的,所以我在这里设置了一个简单的 node.js / express.js / mongodb 应用程序,我的配置如下。

var express = require('express'),
    mongoose = require('mongoose');
    http = require('http');

var app = express();

    app.configure(function()
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');

    //middleware stack
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(__dirname + "/public"));
);

mongoose.connect("mongodb://localhost/hello");

问题出在我尝试发出 PUT 或 DELETE 请求时。我的表格就是这么简单

<form method="POST" action="/users/#user.name">
    <input type="hidden" name="_method" value="PUT"/>
</form>

现在我的路由器使用 express .put() 方法捕获路由

app.put('/users/:name', function(req, res) 

    var b = req.body;

    Users.update(
         name: req.user.name ,
         name: b.name, age: b.age, email: b.email ,
        function(err) 
            res.redirect('/users/'+b.name);
        );
)

当我提出请求时,我只会收到“Cannot PUT”或“Cannot DELETE”错误。

我尝试通过 chomes RESTful 客户端发出同样的请求,结果相同。

我读过一个话题,女巫和我有同样的问题,尽管按照 cmets 的答案并没有解决我的问题。

我研究过的问题 expressjs support for method delete and put without the methodoverride

Are the PUT, DELETE, HEAD, etc methods available in most web browsers?

还有其他一些人。 我还多次引用了 express.js 和 mongo 文档。 我只是想不出哪里出了问题。

感谢任何帮助。

【问题讨论】:

您找到解决方案了吗?我正在做同样的事情,但似乎无法通过 DELETE。 你最终做了什么?我有同样的问题 - ***.com/questions/17603372/… @Mike 我接受的解决方案如下。 @DanielTate 由于您执行了“回滚到修订版 2 - 编辑批准被帖子所有者覆盖”:从答案看来,您要求“不能 PUT ...”或“不能DELETE ...”错误应该被引用为错误,大写的C在“Cannot”中,而不是好像不能放在“bad English”中。标头应该类似于Express "Cannot PUT ..." / "Cannot DELETE ..." error: How to get the PUT / DELETE method working in Express? @questionto42 这是复制+粘贴。无需更新任何内容。 【参考方案1】:

更新

正如 Jonathan Lonowski 指出的那样,PUT 也可以使用,因此您可以忽略我的旧答案。 出现Cannot PUTCannot POST 错误,意味着您的回调未成功执行。我的猜测是 Users.update 失败了,这就是它不能 POST 或 PUT 的原因。你能检查一下吗?

旧答案

尝试更改此行

app.put('/users/:name', function(req, res) 

app.post('/users/:name', function(req, res) 

因为您正在尝试提交表单

【讨论】:

html 表单只有两种有效的方法 GET 和 POST。 @user568109 嗨,你能更新你的答案吗?它是“快递不工作”的谷歌#1,但它没有回答这个问题。我遇到了同样的问题,花了 1 个小时才找到答案:当我们在 put 方法中重定向时,它会重定向到另一个 put。所以我们得到Cannot PUT 错误。请参阅我的答案:***.com/a/57577635/4718434 在对 DELETE 请求和覆盖包进行了 3 天的深入搜索后,这个答案让我松了一口气。谢谢@user568109。 在对 DELETE 请求和覆盖包进行了 3 天的深入搜索后,这个答案让我松了一口气。谢谢@user568109。【参考方案2】:

您列出的&lt;form&gt; 是在视图中还是在__dirname + "/public" 下的static 文件中?

在静态文件中,#user.name 可能不会被username 替换,而是将被视为URL Fragment。

&lt;form&gt; 实际上会提交给/users/ 而不是/users/:name,因为那是path

console.log(url.parse('/users/#user.name'));

 hash: '#user.name',
  pathname: '/users/',
  path: '/users/',
  href: '/users/#user.name' 

&lt;form&gt; 应该从视图中生成,如果不是,因为action 需要是动态的和数据驱动的。使用 Jade 并假设 userlocals 的成员,那就是:

form(method='POST', action='/users/' + user.name)
  input(type='hidden', name='_method', value='PUT')

【讨论】:

我正在使用玉模板,我很抱歉,但这是伪代码,正如我在响应中看到的那样,名称正在被替换,但例如“Cannot PUT USERNAME”【参考方案3】:

除非有奇怪的魔法在起作用,否则您的表单会发出 POST 请求,而不是 PUT。如果你想 PUT,我建议使用带有type: 'PUT' 参数的jQuery.ajax 函数,例如来自表单处理程序的this answer,请参阅jQuery.submit。不要忘记return false 这样表单就不会提交两次。

【讨论】:

在我阅读的所有快速文档中,它们暗示您可以使用表单中的隐藏字段来实现 PUT 请求。 是的,这听起来很神奇 :) 你能提供参考吗? this 是文档的副本。我想知道自此版本以来 PUT 的正确方法是否已更改。不幸的是,该教程中没有列出任何版本。我一直在看一些关于 nettutsplus 的教程,他们使用相同的方法,尽管在他们的文档中他们声明他们使用的是 express 的 3.0 版本,而我使用的是 3.1。 这是一个巧妙的技巧,有时我使用 jQuery 的唯一原因是访问整个 HTTP 词汇表。我当然不会期望在次要版本号更新中出现这样的破坏性更改。我唯一能想到的就是在客户端尝试另一种方法,以消除存在服务器端问题的可能性。不过,我同意您的方法更加优雅,并且仅针对该功能继续使用 Express 3.0 可能是值得的(如果它实际上已被删除)。 一句话:不要返回false。在提交处理程序的开头使用 event.preventDefault。【参考方案4】:

如果您的 using 方法覆盖,请确保在使用路由之前已声明它。这就是我遇到的问题。

【讨论】:

【参考方案5】:

app.post("/movies/:id") 是一种解决方案。 如果您仍想使用 app.put("/movies/:id"),请尝试以下操作:

    从 npm 安装 method-ovveride。 在您的 app.js 文件中需要它。 打开要调用 PUT 请求的表单

    确保您的表单具有以下属性:

    action="/movies/?_method=PUT " method="POST" >

这两个解决方案对我有用。如果您遵循 REST,则使用方法 ovveride else app.post() 也可以解决问题

【讨论】:

我认为值得一提的是 是 ejs。所以它对 OP 不起作用,因为他正在使用玉石。【参考方案6】:

res.redirect('path') 更改为res.redirect(303, 'path')

PutDelete中,如果你想重定向到get地址,你应该传递303作为第一个参数。(source)

【讨论】:

【参考方案7】:

一种解决方案是在 app.js 文件中为您的 PUT、PATCH 和 DELETE 请求使用 cors 中间件,如下所示:

首先通过 npm 安装 cors 包:

npm i cors

然后将以下代码添加到您的 app.js:

const cors = require('cors')

app.use(cors())

【讨论】:

以上是关于Express 无法 PUT/DELETE 方法。出了啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS Express - 幕后GET / POST / PATCH / DELETE之间的区别

Ajax中Put和Delete请求传递参数无效的解决方法(Restful风格)

使用Ajax (put delete ) django原生CBV 出现csrf token解决办法

可以发送 PUT/DELETE 方法的负载测试工具

使用 PUT/DELETE 方法休息框架的“CSRF 令牌丢失”

REST模式中HTTP请求方法(GET,POST,PUT,DELETE)