当前位置:Gxlcms > PHP教程 > RESTfulGET,如果存在大量参数,是否有必要变通一下?

RESTfulGET,如果存在大量参数,是否有必要变通一下?

时间:2021-07-01 10:21:17 帮助过:9人阅读

比如设计一个GET接口,用来获取满足条件的商品
GET shop/1/goods?
参数可能是五花八门的,name,create_time,description, status, owner...

通常这种情况,如果不考虑RESTful,就会设计成POST。

但是现在RESTful风格要求做成GET,如何处理会比较合适?

回复内容:

先说结论,可以,使用POST来处理参数比较长的search请求并没有违反REST。

再说说@张立理 同学的答案里可以改进的地方。在张同学的理论主义玩法里:
有这样的URL:
/goods/ 商品集合
变通不是必要的。如果是因为URI可能超长,导致了某个组件不支持,那么换一个组件就好了。

根据 Fielding Dissertation: CHAPTER 6: Experience and Evaluation 6.3.2.5 Size Limits 里提到的:
There is no limit in the HTTP protocol on the length of URI
尽管
Although older Web clients have a well-known problem with URI that consist of more than 255 characters
解决方法是:
applications within a controlled context (such as an intranet) can avoid those limits by replacing the older components
首先承认超过GET的URL总长度的情况确实可能存在的,一个比较典型的场景就是多选id,鬼知道一个变态能选出多少个来

当然一个合理的应用不应该让这种情况出现,毕竟用手勾选到能超过URL的长度限制应该是会抽筋的,我们亲爱的产品组应该为用户着想
至于“全选”和“全选后取消几个”这种场景,其一我很怀疑后者的用户场景是否真的存在,其二可以使用全选和反选标记来给予实现,也并不是什么麻烦事儿

继续说真的超过了URL长度限制怎么办,第一反应自然是拿POST来玩,但是使用POST除去教条式的语义性和REST规范之外,一个很严重的影响是无法使用HTTP缓存
当然这个也不是什么大问题,毕竟99.99%的应用是不会精心设计HTTP缓存的(是的这句话是在喷包括自己在内的很多工程师),所以搜索这种场景从一开始就几乎是没有HTTP缓存支持

那如果我还是想要缓存,还是想要遵守REST规范使用GET怎么办呢?这里有一个理论主义的玩法
假设我们对商品进行检索,有这样的URL:

/goods/ 商品集合
get也可以带body 楼主的问题是一个很典型的问题,经常有人问我。我的回答一律是:别折腾了,你们根本就做不了RESTful。

绝大部分人都理解RESTful是一种接口的设计形式,然后发现很多时候某些需求根本没法做成RESTful形式的,但就我看来RESTful是从底层架构就应该考虑的问题,或者说是一种架构设计思想,而不仅仅只针对于接口。

比如题主的这个情况,如果要让我来做,我会设计两个接口
POST /shop/1/query 新建一个商品的查询,返回id
GET /shop/1/query/{id} 获取某个查询的结果

为什么要这么设计?
1.RESTful中,URI代表资源,html/图片这类文件是资源,query这类服务也是资源
2.RESTful中,POST用来新建或者更新,GET用来获取资源

但是很显然,这肯定不满足题主的需求,要这样做现有的架构肯定满足不了,所以我劝题主别折腾什么RESTful了,怎么好做怎么来 ---更新 20160213 ---

突然发现貌似 Polyfill 的方案好像和 @立青 童鞋的想法类似。。

---更新 20160213 ---

正如 @张立理@刘尚奇 所说,确实查询条件过长的情况有可能存在,但是倾向于认为其设计的 API 过于复杂(对于每一种 Entity 的接口,都要另外设计一个 Query 的接口),并且导致了有条件查询和无条件查询接口的不一致性,以及使用了一个没有确切 Representation 的中间类型。所以在此重新给出一个简洁一致的通用接口。

1. 无条件查询:


直接 GET。
GET /goods HTTP/1.1
GET /xxx?type=[1|2|3|4|5|6|7|8] 百试不爽,但是!别打我!前端用的也挺happy的⋯⋯ 要么是get带query string,要么是post带body。get带body不符合http规范,这么做有后患。

权衡因素:
  • query string的长度限制,因客户端浏览器(Firefox, Chrome, IE)和服务器(Apache, IIS)而异。query string除了普通的键值对,还可以包含集合参数,后者是有可能超出长度限制的,要小心
  • get+query string对cache更友好
  • get+query string可加入浏览器收藏夹
  • get+query string对搜索引擎更友好
对于复杂search做成post,不见得就违反了Restful。你可以理解为,每次search的结果是一个新创建的临时集合。 restful本来就是拿来装的,没必要那么较真 首先,REST 是一种设计风格而不是标准,如果一个架构符合 REST 原则,我们就称它为 RESTful 架构。

其关键就在于如何抽象资源,抽象得越好,接口设计也就越加符合 REST 风格,即能够享受到更多 HTTP 所带来的「好处」,要知道 Roy Fielding 是在完成 HTTP 1.1 设计之后才回到大学读博,在博士论文中总结出了 REST

然而,如同所有程序世界的矛盾一样,现实中的抽象问题永远无法得到完美的映射。

=====================进入正题=====================

搜索能不能抽象成一个资源,这取决于你怎么看待和使用这个接口。通常来说一个资源会有 CURD 几种接口,如果硬要套用REST的理念对应到「搜索」这个资源其实可以这么理解:

拆分成 create(POST)和 read(GET)这两种接口,create 通过 POST 方法把关键字传给服务器创建一个资源,然后再通过 GET 方法显示最后的搜索结果。

而与此同时还有一个好处就是记录用户的搜索历史,一个用户资源链接着多个 Search 资源,每个资源只有自己的 GET 方法,只不过是我们没有在服务器提供其他方法的映射。

人气教程排行