1
legendlee OP 另外,我感觉如果按照我这样的理解,那么我们完全有可能设计出一种 dsl 描述语言,把各种资源对象的结构和约束,以及操作的鉴权等描述出来,然后编写一个生成器,把基本的前后端逻辑代码生成出来,至少大部分模块生成出来(和数据库无关的部分)。
请问这么做现实吗?有没有现有的这样的系统? |
2
msg7086 2015-10-02 04:31:06 +08:00
不太确定你的理解是否正确,反正我们是肯定得允许额外动词的。
#1 楼 你说的是 Rails generator 吗 |
3
ryanemax 2015-10-02 08:51:08 +08:00 via Android
Restful api markup language
raml.org 官网 背后支持 angularjs 团队, mule raml2html raml 转 html RAMLang angular 生成 Api Design mule 大开源的 ide Demo: api.anasit.com api.anasit.com/doc raml.anasit.com |
4
matsuijurina 2015-10-02 08:53:07 +08:00
建议楼主去尝试一下 rails scaffold ,会豁然开朗的。
|
5
ryanemax 2015-10-02 09:13:51 +08:00 via Android
|
6
legendlee OP @ryanemax 嗯,谢谢,这东西好。有点孤陋寡闻了。最近用 nodejs 搞了个简单的内容管理,里面有些东西就是自己写代码生成的,但是比较简陋。
|
7
xavierskip 2015-10-02 09:51:52 +08:00
URL 用来定位资源, HTTP 描述操作。
|
8
Lucius 2015-10-02 10:09:48 +08:00
“ RESTful 架构有一些典型的设计误区。
最常见的一种设计错误,就是 URI 包含动词。因为"资源"表示一种实体,所以应该是名词, URI 不应该有动词,动词应该放在 HTTP 协议中。” via: http://www.ruanyifeng.com/blog/2011/09/restful.html |
9
imzshh 2015-10-02 10:35:37 +08:00
URL 在 REST 风格的 api 里面只是用来定位一个资源,用不用动词,是不是出现 query string 都没问题。其它内容像是如何利用现有的 HTTP 协议表示 CURD 等操作,处理错误、缓存,怎么进行并发控制、身份验证等等,这些约定才是 RESTful 的精髓。
|
11
imzshh 2015-10-02 10:44:52 +08:00
@Lucius 这种说法才是对 RESTful 的错误认识,这里说的资源是一个抽象概念,出现动词并不会改变它是一个资源的本质。并且在真正 RESTful 的服务器和客户端的交互中,客户端并不关心 url 的格式是怎样的, url (也就是资源)都应该由服务器(通过类似 html 里的链接的方式)告诉客户端,而不是客户端自行生成。
|
12
Lucius 2015-10-02 10:50:19 +08:00
|
15
canesten 2015-10-02 10:57:36 +08:00
@Lucius
所以一个合格的 Restful 的站就是按照不同 HTTP 动词对 URL 资源进行增删改查? 我是觉得只有 GET,POST,DELETE,PUT 好像并不能表达一些复杂的业务。 还是说 Restful 的设计就一定要避免复杂业务? |
16
Lucius 2015-10-02 11:01:51 +08:00
|
17
imzshh 2015-10-02 11:08:40 +08:00
@Lucius 这么说吧, URL 中不出现动词当然是极好的,但是有时候难免会出现不得不出现动词的情况。传统的带?和&的 URL 在 REST 风格的接口中也是可以出现的,进行查询( query 不是 get )的时候也应该使用。我想要表达的是 URL 怎么设计只是整个 REST 架构风格中很小的一点,不要认为 URL 没有出现动词没有?和&了就 RESTful 了,反之就不是 RESTful 了。
|
18
canesten 2015-10-02 11:13:02 +08:00
|
19
hantsy 2015-10-02 11:16:46 +08:00
@legendlee 参考这里讨论。 http://www.v2ex.com/t/221304
@ryanemax RAML 从一开始回到了 SOAP 的老路,这是使用 REST 的程序员最不希望看到。记得使用 SOAP 的时候,讨论的一个最基本的问题就是 Contract First 还是 Code First ,基于 SOAP 多于牛毛的各种规范,导致 Contract First 占优势。从技术人员的角度看,大部分都是愿意使用 Code First ,这也是 REST API 很盛行代替 SOAP 的原因。 RAML 最初也是 Swagger 描述中抽象出来的。 Swagger 初衷是可视 REST API ,我已经在项目已经使用了两年以上 Swagger 。但 Swagger 不支持 REST API Rechardson Model Level3 , 如 HAL 等。 HAL Browser 更简单一些。 |
20
initdrv 2015-10-02 11:20:20 +08:00
看看大牛们的见解,新手 mark 一下!
|
21
imzshh 2015-10-02 11:23:18 +08:00
@Lucius 阮大的文章当成科普文看看就行了,当成教科书来学习还是不合适的。在 RESTful 具体实践中多得是比“ URL 中能不能出现动词”这样的问题更加重要的问题要去解决,没必要在这个问题上多纠结。
看看 github 的 search api : https://developer.github.com/v3/search/#search-repositories |
22
hantsy 2015-10-02 11:28:46 +08:00
@imzshh 大部分情况是可以利用 HTTP 语义避免,少数情况下不得回避这些原则(如 /auth/signup, /auth/signin, 查询参数太多时,可能改 POST 查询,通过 Body 传递更多的参数)。 Github API , Heroku 是设计上比较的 API 典范。
REST , Rechardson Mature Model 都是约定,不是规范。 但 HAL 是规范。 |
23
yangyuan 2015-10-02 11:33:26 +08:00
RESTful 本身 url 里只有可能有两种实体。
资源 和 服务,这样设计的目的是动词可以用 HTTP 的方法来代替。 私以为 RESTful 是一种 API 设计的规则样式,但这个规则样式并不是最直观方便的,也不是很适合浏览器。 很多被认为“错误”的用法,完全可以另总结为 “ ACTIONful ”,“ WEBful ” 什么的。 |
24
imzshh 2015-10-02 11:34:32 +08:00
@hantsy 是的,所以我一直说的是风格而不是规范。
PS :你例举的这个可以用 POST /access-tokens, DELETE /access-tokens/<token> 这样的 URL 形式。 |
25
codeek 2015-10-02 11:49:22 +08:00
RESTful 的简单理解,可以分成三个层次:
1. 所有的 URL 指代的对应物都是一组资源 - resources; 2. 基于 1 ,自然不适合在 URL 中使用任何动词,所以推荐直接使用 HTTP 标准中的动词(verb: GET, PUT, POST, DELETE)来表示对资源的操作; 3. Hypermedia as the Engine of Application State(HATEOAS). 简而言之,服务器的每次响应中应该包含当前请求资源所有相关联资源的定位信息。举个例子:请求分页,如果下一页请求已经枯竭,那么本次请求的响应中应该标识下一页请求的定位 URL 为空。 |
26
semicircle21 2015-10-02 17:36:45 +08:00
@Lucius
@imzshh @canesten url 可以用动词的名词形式, 比如 对这个主题的点赞操作, 我可能会设计成这样: https://v2ex.com/t/225164/upvoters 点赞就发 post, 获取点赞者列表就 get, 删除就往这个 url 上发 delete. 是不是动词没什么好纠结的, 真正实践 restful 的时候, 远有比这个麻烦的多的坑... 特别是面向移动客户端的时候, 完全按 restful 设计往往导致一个界面要好几个请求才能加在完, 体验像 shi 一样. |
27
msg7086 2015-10-02 20:14:42 +08:00
@Lucius 「上菜了,请动筷子吧」 = 禁止筷子以外的餐具
资源如果只能做 CRUD 动作的话,就等于要把一大票业务流程都归并到 Update 上,反而造成接口混乱。 比如我要有购买商品功能,要怎么设计路由? |
28
karloku 2015-10-03 04:01:47 +08:00
其实参考了 elasticsearch 的 api 设计方式, 觉得 uri 里包含动词也不是一件天崩地裂的事情, 也就是在 crud 之外.
比如我有一串资源是 /items, 这些 items 是支持排序的, 那么我排序的接口应该怎么设计呢. PUT /items { "_action": "reorder", "params": {...} } 这样似乎就会污染 update 这个街口, 变得很复杂 把路由放到 PUT /items/orders 操作实际上不存在的 orders 资源. 总觉得有种自欺欺人的感觉. 这种做法最常见的是用在搜索或者点赞上. 但是前者的确因为请求而产生了一次性的资源. 而后者也是可以勉强算是嵌套在某个资源内部的资源. 或者是针对所有资源进行 PUT /items/x 去更新每一个 item 的 order. 这个好像 restful 了, 不过使用起来会变的非常麻烦... 最后尝试下来做下来还是包含一个动词的 URI, 会让 api 的语义更清楚: POST /items/_reorder |
29
legendlee OP @msg7086 没做过电商系统,但是按照之前做管理系统的经验,购买商品这种操作,在系统内部应该叫“创建一个订单”吧。
|
30
SmiteChow 2015-10-06 21:10:37 +08:00
最标准的 restful 可以参考 swagger 设计
|