详解 RESTful API 中的动词覆盖

今天,写篇文章介绍一下 RESTful API 中的动词覆盖吧。

在开发各种小程序的时候,总是会遇到不能正常支持 HTTP 请求的平台,比如支付宝小程序只支持 GET 和 POST 请求,这时候充分利用 HTTP 请求方法的 RESTful API 就会遇到问题,不支持 PUT, PATCH, DELETE 请求,该怎么办呢?嗯,使用动词覆盖。


什么是动词覆盖

我最初遇到不支持全部 HTTP 请求的时候,解决方案是修改 API 路径,比如 DELETE /user/:id 时,我的方案是 POST /user/:id/delete。后来看了阮一峰的《RESTful API 最佳实践实践 》,才明白有动词覆盖这回事儿,感觉动词覆盖确实更优雅,手动狗头。。。


有些客户端只能使用GET和POST这两种方法。服务器必须接受POST模拟其他三个方法(PUT、PATCH、DELETE)。

这时,客户端发出的 HTTP 请求,要加上X-HTTP-Method-Override属性,告诉服务器应该使用哪一个动词,覆盖POST方法。

POST /api/Person/4 HTTP/1.1  
X-HTTP-Method-Override: PUT

上面代码中,X-HTTP-Method-Override指定本次请求的方法是PUT,而不是POST。



前端

前端的工作就是在请求的 header 中添加字段 X-HTTP-Method-Override,举个例子,比如我使用了 uniapp 的插件 luchAPI,在请求的时候我设置了请求的 option。

var url = "/user/"+that.$store.state.userInfo.id;
that.$http.post(url, req, {header:{'X-HTTP-Method-Override':"put"}})
 .then(res=>{
  console.log("res:", res);
  if(res.statusCode == 200){
   console.log("update prfile: ", res);
   that.$store.commit("setUserInfo", res.data);
   uni.showToast({
    title:"修改成功",
    icon:"none"
   })
  }else{
   uni.showToast({
    title:res.error,
    icon:"none"
   })
  }
 });



后端

后端使用的是 ThinkPHP 框架,本来准备自己实现请求覆盖的,虽然 ThinkPHP 官方的文档中没找到,但是看了下源码,居然体贴实现了这个功能,下面是 ThinkPHP 框架的源码。


ThinkPHP 5.0.24 中 \thinkphp\library\think\Request.php


/**
    * 当前的请求类型
    * @access public
    * @param bool $method true 获取原始请求类型
    * @return string
    */
public function method($method = false)
{
    if (true === $method) {
        // 获取原始请求类型
        return $this->server('REQUEST_METHOD') ?: 'GET';
    } elseif (!$this->method) {
        if (isset($_POST[Config::get('var_method')])) {
            $method = strtoupper($_POST[Config::get('var_method')]);
            if (in_array($method, ['GET', 'POST', 'DELETE', 'PUT', 'PATCH'])) {
                $this->method = $method;
                $this->{$this->method}($_POST);
            } else {
                $this->method = 'POST';
            }
            unset($_POST[Config::get('var_method')]);
        } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
            $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
        } else {
            $this->method = $this->server('REQUEST_METHOD') ?: 'GET';
        }
    }
    return $this->method;
}



Koa.js 可以使用 https://github.com/koa-modules/methodoverride

真诚赞赏,手留余香
赞赏
随机推荐
Git命令文本手册
设计的四个基本原则
CentOS 如何防止 SSH 长时间不操作自动断开连接
Android工程中添加图片资源
Git 工作流程
HTTP 协议入门
为什么Axios ajax每次patch都会有两次网络请求?
PM2 负载均衡
Android Studio卡在refreshing gradle project的原因和快速解决办法
Windows server 2003 iis安装php