最近在写一个应用,涉及到几个外部数据源的操作,API 设计上有一些矛盾,大家觉得哪种好,还是有其他的设计?
- 创建数据源
POST /data-source
- 获取支持的数据源国外服务器类型列表
// 感觉 URL 太长
GET /data-source-type
// 跟 GET /data-source/{id} 重叠了
GET /data-source/types
- 提供连接参数,检测数据源是否可用
POST /data-source-check
POST /data-source?action=check
- 创建之前初始化数据源,比如创建 MySQL 表
POST /data-source-init
POST /data-source/init
POST /data-source?action=init
总结来说就是 对象未创建之前进行的一些操作怎么设计,比如:
检查用户是否存在 vs 创建一个用户
如果都是操作 data-source 的话,可以加个类别
例如:/data-source/detail/1 、/data-source/types 、/data-source/init
在 URL 的设计上我觉得能够语义清晰就可以了。
“获取支持的数据源类型列表” 我认为两种设计都可以,甚至 `GET /data-source?filter=types` 这样也可以,都是表达只获取 types 。
但 “提供连接参数,检测数据源是否可用” 我认为不应该用 POST 方法,ping 这种行为在我看来应该是安全且幂等的,应该用 GET 方法。所以这里合适的设计应该是 “GET /ping-data-source”
在我看来你的思考矛盾主要在于:你认为 HTTP Methods 都是针对资源的操作,而这个资源又被局限于实体存在的资源。
但这个资源实际上可以是抽象的、动态的,比如说用 RESTful 风格设计最常见的问题就是 “登录” 这个接口如何设计。其实只需要 `POST /login` 就可以。从 HTTP POST 方法本身的语义讲,是完全支持这样做的,它并不是单纯的用于创建资源的语义。rfc 文档中关于 POST 能力的部分解释:“Providing a block of data, such as the fields entered into an HTML form, to a data-handling process;”
补充一点,我看的一本关于 RESTful API 的书里吐槽过这个解释,因为这个 “data-handling process” 含义太过模糊,所以现在有人的接口设计为全用 POST,其实也是符合 HTTP 语义的,因为任何操作都能引申为数据处理......
1. POST /data-source
2. GET /data-source/_types
3. POST /data-source/_ping
4. POST /data-source/_initialization
用 _ 来表示 meta 操作,是完全可理解、且常规的。而且越不常见的操作名字应当越完整、最好长得多。
但是令我迷惑的是,为什么会有单独的 4. 操作?不应该 1. 操作时直接做掉吗?
POST +header 或者 body 里传参
RESTful 表面上看起来优雅,但真的不好用(不容易用好),用起来很烦。
现在我的个人项目已经完全放弃 RESTful, 改成 GET POST 走天下。
因此我觉得 GET /data-source-types 就很好,语义非常清晰,也没有比 GET /data-source/types 更长(长度一样)。缺点只是从 RESTful 的角度看不够优雅(我个人认为那种优雅带来的麻烦比好处多)。
你这样不方便权限控制
GET /data-sources
POST /data-sources/types
POST /data-sources/actions/check
不能使用 RESTful 表达的一律使用 POST 作为 “Function” 调用
我就喜欢在接口名字上尽量把用途体现出来。这样就很直白,看接口名就知道做什么的,并不需要再去看参数列表
权限控制不在这一层,因为楼主还有一个 GET /data-source/{id}, 因此 data-source 就只有一个,没有 data-source1 、data-source2 (因为那就应该是 /data-source/1 、/data-source/2)
因此只有一个全部数据源共用的 /data-source-types,不需要区分 /data-source1/types 、/data-source2/types
不对,你想错了