比如,对于资源 Post, 请求一个资源的的地址为 http://example.com/posts/1 请求一个命名集合(collection)的资源,比如最新的 posts,可以用 http://example.com/posts/recent
如果我想请求多个离散的资源,比如 id=2, id=12, id=13, id=4,可以访问 http://example.com/posts/:id 这个接口 4 次,但这样多次请求,效率不高;在实际使用中,结合其他接口,很有可能出现类似于 SQL 中的 1+N 问题。所以希望在一次请求中,返回满足要求的结果。
SO 上有一个讨论: How to construct a REST API that takes an array of id's for the resources ,提到可以用类似
http://example.com/posts/?id=2,12,14,4
这种形式的接口。但是根据Query String的规范:
Letters (A-Z and a-z), numbers (0-9) and the characters '.','-','~' and '_' are left as-is SPACE is encoded as '+' or %20[citation needed] All other characters are encoded as %FF hex representation with any non-ASCII characters first encoded as UTF-8 (or other specified encoding)
所以 Query String 里的,
应该用%2C
代替,所以上面的 URL 应为
http://example.com/posts?id=2%2C12%2C14%2C4
这样看起来很别扭。有没有其他的解决方案呢?
其实用 rails 的风格,数组应该使用id[]=2&id[12]&id[]=14&id[]=4
,查询串应该为
> {:id => [2, 12, 14, 4]}.to_query
=> "id%5B%5D=2&id%5B%5D=12&id%5B%5D=14&id%5B%5D=4"
这个更别扭了⋯⋯
有两个问题:
http://www.infoq.com/cn/news/2008/12/restapi-must-be-hypertext-driven
楼主的问题实际上是所谓批量操作的问题
对于批操作,Fielding认为人们觉得需要批操作是因为他们没有理解资源的范围。他指出资源并非存储项(至少不等同于后台中某些存储项),并且同一资源状态可以由多个资源来分担。如果谁发现他需要一个批操作,那么很可能只是因为他没有定义足够的资源。(回复#21)
所以,如果你要简单,那么不必纠结, http://example.com/posts?id=2%2C12%2C14%2C4
没有任何问题。
如果你要追求 REST,那么应该考虑的是,你为什么要用零散的 ID 数组获取一组资源,也许你需要的是定义另外一个资源抽象,这个新资源包括了那些零散的资源
#10 楼 @huacnlee http://www.boutell.com/newfaq/misc/urllength.html 不同浏览器不同。一般如果怕 url 太长,就 post 吧
Rails 通常的 routes 按理说应该成为原子性的 API 接口,你可以在 controller 中对其进行扩展,同时提供多个资源。但是如果你不想把网站现在用的 controller 搞得一团糟,你可以把 api 的逻辑分开来写,独立成另一套 controller,你可以参考下 teambox 这个在 github 上的项目,虽然我觉得有点重复,不过他们的 api 写法确实能够解决问题。
#9 楼 @fsword LZ 的问题确实是批量操作的问题,不过在某些时候,我们并不好把客户端要传过来的 ids 抽象成资源,比如操作是在需要操作邮件这类的 list 的列表时,我们无法预知用户到底是要操作哪些邮件,因此这类我们怎么抽象?不过我认为您例子里面的 http://example.com/posts?id=2%2C12%2C14%2C4这样就很好了。也同时期待有更为优雅的解决方法。
#17 楼 @fsword @zhangyuan 其实我对 LZ 的要批量操作一个无规律的数组的用的地方也有些疑问。如果是 post、put、delete 的操作并不应该把 ids 出现在 paramters 里面,丁丁说用 post 也许也是在指批量操作吧(我不代表他的意思)。好吧有点偏题了,不过正如@fsword 所说,什么应用场景下必须处理一个不可预知的 get 请求呢?
#19 楼 @hisea 这句话挺对的@poshboytl一直不是推崇要从实际出发有意 break 吗?要真把 current_user 抽象成单独资源也太傻了。??我歪楼了???