今天,写篇文章介绍一下 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