我正在努力理解RESTful设计,并希望用社交网络的术语来理解它。我已经阅读了 REST API Design Rulebook,查看了其他一些书籍并阅读了许多在线资源。然而,在将规则应用于实际问题时,我意识到我并没有完全理解所有内容。我想通过指定一些问题来确定我是否正确理解了REST:
层次结构与平面设计
假设我用某个特定用户来标识一个用户
/users/42
现在,该用户上传的照片将会出现在......
/users/42/photos
如果他/她在照片中标记了他/她的朋友,这些标记将出现在...
/users/42/photos/1337/tags
但是这种方法无法找到所有标记了特定用户的照片。我应该为此想出一个不同的层次结构吗?这似乎有点尴尬。我可以完全忽略层次结构,并提供与此类查询相结合的照片吗?
/photos?owner=42
/photos?tagged=42
当内容针对不同用户有所不同时的缓存处理
一个Web服务应该被设计成提供可缓存的数据(以便客户端可以决定使用本地副本,如果它认为没有任何更改),但这如何影响不同用户的隐私设置?两个已登录的用户可能拥有查看关于例如用户42的不同信息的权利。这是否意味着我需要为访问同一用户的配置文件信息的不同用户请求不同的URI,或者只要用户提供不同的凭据,缓存就不会成为问题?
同时从同一资源提供HTML和JSON/XML
我提到的书规定API应该在以api
开头的子域名下访问,例如http://api.soccer.restapi.org
。我原计划在同一个控制器上为用户访问和机器访问(例如移动应用程序)提供服务。控制器将通过HTTP请求标头中的Accept
字段决定要提供哪个视图(text/html
、application/json
或application/xml
)。我认为这可能是个坏主意(因为用户希望看到子域名www
而不是api
),但我不明白为什么会这样。请问www
和api
可以指向同一台服务器吗?或者我真的需要尝试将HTML视图移到另一个虚拟主机上吗?为什么?我相信Ruby on Rails会(惯例优于配置)从同一个控制器提供HTML和JSON,因此共享了我的想法:HTML和JSON只是相同数据的不同表示形式。
换句话说,我的书指出某一资源应该只有一个URI,并且应根据“Accept”字段提供不同的表示形式。在不同的子域之间重定向用户会违反提供同一资源的规则,而复制信息(即将两个子域指向同一虚拟主机)会违反不为同一资源提供多个URI的规则。不提供“api”子域还违反了另一个设计规则。我如何在不违反任何规则的情况下解决这个问题?
限制返回的数据量
查询组件应用于分页,但是我可以拒绝没有搜索条件的列表请求并限制项目数量吗,而不违反REST?我既想减少数据库负载,又想避免有人映射整个用户目录。我希望…
/users
成为非法请求,同时
/users?name=leet+hacker
这个查询是有效的,但只会返回100个项目。
我也想知道是否可以合法地返回数据库列的子集,仅在使用查询明确请求更多/全部列时才返回它们。
控制器提供冗余数据
我认为提供像这样的控制器是合法的
/users/me
但它是否应该提供与文档URI完全相同的信息呢?
/users/42
还是应该重定向到它吗?
某些用户的扩展权限
提供额外功能的RESTful方法是什么,例如管理权限?我现在假设管理员(照片,用户组或整个站点的管理员)将能够查看有关特定对象的更多信息而其他用户则不能。这些信息是否应保留在完全相同的URI上并自动发送给管理员但不发送给其他任何人,是否应存储在不同位置,是否应使用某种管理员查询请求或以其他方式提供?
本地化和设置更新
虽然用户可见的大部分字符串应该由视图提供,但有些设计决策可能涉及API。最明显的是名称。社交网络有时允许用户输入不同的名称,在不同的语言环境下显示。某些语言中的名称,如俄语和阿拉伯语,不容易自动转录。在其他语言中,例如中文,本地和国际名称可能完全不同,没有任何相似之处或联系。如何以RESTful方式处理这个问题?我觉得答案会涉及到Accept-Language
字段,但是有人认真考虑过在所属的社交网络上切换语言吗?所有这些信息每次都需要返回给调用者吗?还是可以依赖于设置?这样做是否适用于缓存?