前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2020-5-10-RESTfulAPI中能否使用query string

2020-5-10-RESTfulAPI中能否使用query string

作者头像
黄腾霄
发布2020-06-10 15:11:14
5810
发布2020-06-10 15:11:14
举报
文章被收录于专栏:黄腾霄的博客

之前2020-5-6-restful理解 - huangtengxiao和大家介绍了对RESTful的理解。然后就有小伙伴问了我灵魂问题,对于RESTfulAPI设计,是不是不能使用query string?

关于这个问题,网上观点两派纷争不断,为此我特意去拜读了Roy Thomas Fielding的博士论文,以及结合自己的理解来和大家谈谈RESTfulAPI能否使用query string。


问题来源

对于RESTfulAPI,大家都有一个基本的认识,网上一切皆资源,用URI来定位唯一的资源。

而对于领域模型的实体对象来说,RESTfulAPI的设计大家都没有什么疑问。

比如一个人的名字可以用这样的API

代码语言:javascript
复制
/people/1/name

但是,如果这个资源时一个服务,那么处理方式就存在争议了

比如有一个姓名生成服务,可以根据传入的性别,生成一个随机的人名。

不同的同学可能会使用下面两种不同的API设计方式。

代码语言:javascript
复制
/namegenerator?gender=male
/namegenerator/male

出现这种情况的一个可能的原因来自于Roy Thomas Fielding博士论文中的6.5.2 HTTP is not RPC这一小节。

文中不建议大家使用RPC风格的设计(即类似第一种使用query string 的方法)。

那么这一节真的是让大家不要使用query string 么?

HTTP is not RPC

论文里面最重要的一段话如下,翻译过来大意是,HTTP和RPC的区别不在于语法,而是提供了一个带标准语义统一的接口,能让中间层获取和源服务几乎相同的解析能力。这导致应用获得了独立于信息源的转换层和间接层,有利于构建网络缩放,多组织,可松散缩放的信息系统。而RPC机制只是定义了API术语,而不是基于网络的应用。

代码语言:javascript
复制
What distinguishes HTTP from RPC isn't the syntax. It isn't even the different characteristics gained from using a stream as a parameter, though that helps to explain why existing RPC mechanisms were not usable for the Web. What makes HTTP significantly different from RPC is that the requests are directed to resources using a generic interface with standard semantics that can be interpreted by intermediaries almost as well as by the machines that originate services. The result is an application that allows for layers of transformation and indirection that are independent of the information origin, which is very useful for an Internet-scale, multi-organization, anarchically scalable information system. RPC mechanisms, in contrast, are defined in terms of language APIs, not network-based applications.

这段话有几个关键点:

  • 统一接口
  • 中间层解析
  • 可缩放

我们来分析一下,使用RESTfulAPI的好处在于统一的语义化API,让各个中间节点,可以识别请求信息。于是我们可以在网络中间层,添加对应的转换服务,比如缓存服务。

许多的浏览器节点和中间服务器节点(代理服务器,CDN服务器)等,都不支持对query string的缓存。详见:[Revving Filenames: don’t use querystring

High Performance Web Sites](https://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/)

另外的一点,是模型的扩展。例如对于之前的人名API可以做如下扩展,而且这些扩展都可以是按需添加的。而RPC风格的API设计几乎只有不停的添加参数,才能实现。

代码语言:javascript
复制
/people/1/name/firstname
/people/1/name/lastname
/people/1/age

还有一点是content negotiation。RESTfulAPI可以通过http的控制信息来确定返回内容的类型,比如是json还是xml。这里的好处是可以保证URI的稳定,和长生命周期。而这也是某些RPC风格写法(例如type=xml)很难做到的。

服务是叶节点

上面聊了都是不使用RPC风格API的好处,但是对于服务来说,情况会有一些不一样。

首先服务对于领域模型来说,大多数是不属于实体的方法。

因此很难直接将其转换为对于实体的增删改查操作。

第二点,服务的返回值往往都是需要进行运算获得,所以生命周期往往比较短。

第三点,服务作为模型的叶节点,几乎不会再有层次性的扩展。

那么对应于上一小节的限制,几乎不会存在。

  1. 没有层次扩展要求,所以不存在扩展性问题
  2. 现在很多服务也能利用中间层的content negotiation,确定返回值类型。前提只要不写出,类似type=xml的API即可
  3. 及时运算结果和短生命周期,对缓存要求变低。另外目前越来越多的浏览器和服务器开始支持带query string的请求内容的缓存,也能满足长时间缓存的要求。

服务使用query string类型的优劣

上面解释了为什么服务使用query string不存在实体类型使用query string的常见坏处。

这里解释下服务使用query string风格的实际优势和劣势。

语义化优先

实际上Roy Thomas Fielding博士论文一直在强调语义性。

而服务使用query string也是语义优先的。

对于/namegenerator?gender=male我们很清楚male的语义是gender。

/namegenerator/male则相反,male不具有语义,甚至整个uri不对应任何实体,这和RESTful的思想是背道而驰的。

模型优先

假如我们强行将服务转换成实体,用来同时符合RESTful和避免query string的要求。

我们可能会得到如下的API设计

代码语言:javascript
复制
/namegenerator/malenamegenerator/generatednames
/namegenerator/malenamegenerator/generatednames/huangtengxiao

这种设计会使得实现决定模型,让软件脱离模型原有设计,导致软件更加难以理解和维护

RESTfulAPI是否应该使用query string

关于这个问题,我阅读了Roy Thomas Fielding的博士论文。

全文没有一处强调是否对RESTful采用如何的实现。

在我看来RESTful实际上是guide,而不是best practice。

我们应该选择符合RESTful的约束思想的实现,而不是被实现约束。

个人推荐做饭

纯属个人推荐。

  • 对于领域模型中的实体类型,使用层次化的名字形式API
  • 对于领域模型中的服务类型,推荐使用query string,表示参数

其他方案

当然除了query string,也有其他大神推荐的方案。

比如阮一峰在理解RESTful架构 - 阮一峰的网络日志中就推荐对于服务,使用post方法,然后在http头中带对应的参数。

个人认为这也是一个很好的RESTful实现


参考文档:


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/RESTfulAPI%E4%B8%AD%E8%83%BD%E5%90%A6%E4%BD%BF%E7%94%A8query-string.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题来源
  • HTTP is not RPC
  • 服务是叶节点
  • 服务使用query string类型的优劣
    • 语义化优先
      • 模型优先
      • RESTfulAPI是否应该使用query string
        • 个人推荐做饭
        • 其他方案
        相关产品与服务
        内容分发网络 CDN
        内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档