【问题标题】:Node.js - Express 4.x - method-override not handling PUT requestNode.js - Express 4.x - 方法覆盖不处理 PUT 请求
【发布时间】:2014-07-24 01:03:22
【问题描述】:

我正在尝试让服务器处理 PUT 请求。但无济于事。客户端在提交表单后不断收到“Cannot 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>

【问题讨论】:

    标签: javascript node.js express connect


    【解决方案1】:

    更简单的方法可能是override using a query value:

    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>
    

    【讨论】:

    • 干杯。这以最少的麻烦解决了问题,因此应该被视为最佳答案。
    【解决方案2】:

    method-override v2.0.0(2014-06-01 版)开始,中间件的默认行为不会检查 POST 正文中的 _method 字段;它只检查X-HTTP-Method-Override 标头。

    为了让method-override能够像之前的版本一样运行,你需要给methodOverride提供一个自定义函数,详见the project page

    自定义逻辑

    您可以使用getter 的函数实现任何类型的自定义逻辑。以下实现了在req.body 中查找method-override 1 的逻辑:

    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
      }
    }))
    

    【讨论】:

    • 这是不必要的。下面的答案是正确的,您可以在method-override 文档中阅读here。下面的答案已经表明了这一点。它应该是正确的。
    【解决方案3】:

    我们也可以使用一个简单的中间件来处理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();
        });
    

    【讨论】:

      【解决方案4】:

      您可以选择如何覆盖:

      // 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
      

      【讨论】:

        【解决方案5】:

        我刚刚开始构建我的第一个 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)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-26
          • 1970-01-01
          • 2013-09-06
          • 2014-08-26
          • 2018-03-26
          • 2019-10-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多