Node.js - Express 4.x - method-override 不处理 PUT 请求。

18

我尝试让服务器处理 PUT 请求。但是一直不成功。客户端在提交表单后一直收到“无法 POST /”消息。 我正在使用Express 4.x。

请注意,如果我在路由中将“put”更改为“post”,则请求将被成功处理...

如何让我的服务器处理 'PUT' 请求?

服务器:

var express         = require("express");
var bodyParser      = require("body-parser");
var methodOverride  = require("method-override");

var app             = express();

app.use(bodyParser());
app.use(methodOverride());


app.get("/",function(req,res){
    res.render("index.ejs");
    console.log("GET received.");
});
app.put("/",function(req,res){
    console.log("PUT received: " + req.body.userName + " - " + req.body.password);
});

app.listen(1337);
console.log("Listening on 1337.");

客户端

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
    </head>
    <body>
        <form action="/" method="post">
            First
            <input type="text" name="first">
            Last
            <input type="text" name="last">
            <input type="hidden" name="_method" value="put">
            <button type="submit">Submit</button>
        </form>
    </body>
</html>
6个回答

20

可以使用查询参数来覆盖,这是一种更简单的方法:

var methodOverride = require('method-override')

// override with POST having ?_method=PUT
app.use(methodOverride('_method'))

使用HTML覆盖查询的示例调用:

<form method="POST" action="/resource?_method=PUT">
  <button type="submit">Put resource</button>
</form>

3
干杯。这个解决方案最简单,应该被认为是最佳答案。 - mikeym

13
自从method-override v2.0.0(发布于2014年6月1日)起,中间件的默认行为不会检查POST请求体中是否有_method字段;它仅检查X-HTTP-Method-Override头。
为了使method-override像早期版本一样操作,您需要向methodOverride提供自定义函数,详见项目页面

自定义逻辑

可以使用函数实现各种自定义逻辑作为getter。以下代码实现了在method-override 1中存在的查找req.body的逻辑:

var bodyParser     = require('body-parser')

var connect        = require('connect')
var methodOverride = require('method-override')

app.use(bodyParser.urlencoded())
app.use(methodOverride(function(req, res){
  if (req.body && typeof req.body === 'object' && '_method' in req.body) {
    // look in urlencoded POST bodies and delete it
    var method = req.body._method
    delete req.body._method
    return method
  }
}))

7
这是不必要的。您可以在method-override文档这里中阅读到下面的答案是正确的。下面的答案已经表明了这一点。它应该是正确的答案。 - dav1dhunt

1
我们还可以使用简单的中间件来处理 x-http-method-override
     var router = express.Router();

     /**
     * Middleware that detects a HTTP method tunneled,
     * inside the header of another HTTP method. Detects
     * and routs to the method mentioned in the header.
     */

    router.use((req,resp,next)=>{
        if(req.headers['x-http-method-override']){
            req.method = req.headers['x-http-method-override'];
        }
        next();
    });

1

我刚开始构建我的第一个express项目,下面的代码有效。由于我来自Laravel,我希望我的路由检查_method字段的存在并确定适当的路由。因此,我创建了一个中间件来实现这一点。

import { RequestHandler } from "express";

// Updates the request method if there is a 
// "_method" field present in the request query or
// request body.
const methodOverride: RequestHandler = function (req, res, next) {

    // Set the request method to the "_method" value in query
    // or the request body. Perform a validation before setting the
    // request method.
    req.method = req.query._method || req.body._method || req.method;

    // Carry forward the request to next middleware
    return next();
};

export default methodOverride;

在任何路由相关的中间件之前使用此中间件。现在,我的表单可以看起来像这样

<form action="/" method="post">
    <input type="text" name="first">
    <input type="text" name="last">
    <input type="hidden" name="_method" value="put">
    <button type="submit">Submit</button>
</form>

router.put('/', handler) 将会被执行,而不是 router.post('/', handler)


我正在尝试这个,但它在form-data中不起作用,只能在x-www-form-urlencoded中使用,有什么解决办法吗? - mamena tech
我认为你需要添加一个中间件来解析x-www-form-urlencoded输入。一旦添加了这个中间件,数据就会出现在请求体/查询中。 - Kalesh Kaladharan

0

您可以选择如何覆盖:

// override with different headers; last one takes precedence

app.use(methodOverride('X-HTTP-Method'))          // Microsoft
app.use(methodOverride('X-HTTP-Method-Override')) // Google/GData
app.use(methodOverride('X-Method-Override'))      // IBM

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接