一、需求

为了给 express 增加多种类型的请求方法,需要对请求方法进行覆盖。

express 支持的请求方式如下:

1.jpg

要增加请求类型,可以自定义中间件或者使用 method-override 中间件来完成。

二、自己实现一个中间件

自己实现请求类型也是通过增加一个隐藏的标识字段来实现的。

比如在 GET 或者 POST 请求中,增加一个 __method 字段,值为真实的请求类型。

比如下面的表单,发送 SEARCH 类型的请求:

    <form action="/" method="post">
      <input type="hidden" name="__method" value="search">
      <button type="">submit</button>
    </form>

中间件的原理就是获取到 __method 字段,并且覆盖掉原有的 req.__method

下面的中间方法中,需要注意的是:

  • 如果 query 中存在 __method(主要是GET方式的请求),则覆盖。
  • 如果 body 中存在 __method (POST方式请求),则覆盖。注意需要判断 body 是否存在,是否是对象,是否有 __method 属性。

这种中间件只是演示一下中间件覆写方法的原理

/**
 * @name methodOverride
 * @description 请求方法重写中间件
 */
function methodOverride(req,res,next){
  req.oldMethod = req.method;
  // GET 请求 在query中寻找 __method
  if(req.query.__method){
    req.method = req.query.__method;
  }
  // POST 请求 在 body 中寻找 __method
  if(req.body && typeof req.body === 'object' && '__method' in req.body){
    req.method = req.body.__method;
  }
  next();
}

module.exports = methodOverride;

二、使用 method-override

如果使用 method-override 的话,直接安装中间件,根据文档使用就可以。

安装:

yarn add method-override

method-override 建议,所有的重写方法请求,应当均为 POST

1)通过在 url 中增加 __method=??? 来使用:

如果是直接在 URL 上面手动写上一个 query 参数,则可以直接像下面这样使用:

var express = require('express')
var methodOverride = require('method-override')
var app = express()

// 在 url 中直接加上 ?_method=DELETE
app.use(methodOverride('__method'))

而这样的表单可能如下方式:

<form method="POST" action="/resource?__method=DELETE">
  <button type="submit">Delete resource</button>
</form>

2)通过隐藏字段 __method = ??? 的方式:

如果是和上面自定义隐藏表单字段的方式,则需要通过下面这种方式使用:

相比较而言,我觉得这种方式过于麻烦,不过反正官方已经实现掉了。

var bodyParser = require('body-parser')
var express = require('express')
var methodOverride = require('method-override')
var app = express()

// 注意,如果你使用 req.body 来完成,则首先必须调用 body-parser 进行 urlencode 操作
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
  }
}));

此时的表单可能如下:

<form method="POST" action="/resource" enctype="application/x-www-form-urlencoded">
  <input type="hidden" name="_method" value="DELETE">
  <button type="submit">Delete resource</button>
</form>

3)通过 http 请求头完成覆写

如果做 API ,则可能更加倾向于使用 请求头字段 完成标识。

比如使用这个请求头 X-HTTP-Method-Override

var express = require('express')
var methodOverride = require('method-override')
var app = express()

// override with the X-HTTP-Method-Override header in the request
app.use(methodOverride('X-HTTP-Method-Override'))

则在请求的时候,只需要设置一下请求头即可:

var xhr = new XMLHttpRequest()
xhr.onload = onload
xhr.open('post', '/resource', true)
xhr.setRequestHeader('X-HTTP-Method-Override', 'DELETE')
xhr.send()

function onload () {
  alert('got response: ' + this.responseText)
}