rest - REST API 设计:什么是独特的操作或资源
问题描述
几年前,我创建了一个小型 Web 服务,它以两种表示形式为相同的资源提供服务。
# returns a collection of Foos
GET /foo
# returns the same collection of Foos in a different JSON representation
GET /foo?projection=X with 'Accept: my-specific-media-type'
这在(Java)代码中非常有效,因为我可以将两种方法映射到相同的方法,@Path
它们都具有不同的返回类型。一个接受一个特定的媒体类型,@QueryParam
而@Consumes
另一个不接受。
但是,根据(当前)@ApiOperation
Swagger 注释,我选择了错误的 API 设计。
HTTP 方法和路径的组合创建了唯一的操作
因此,在我将旧项目升级到当前库版本后,Swagger 模型只包含一个GET /foo
操作——这是随机的,因为它依赖于通过 Java 反射进行的运行时代码自省。
所以,问题是这样的:不同表示Foo
的资源实际上是“相同”资源还是不同的资源?Swagger 注释似乎暗示了后者(不同的资源-> 不同的路径)。
解决方案
您遇到的部分问题是 REST 概念和 Swagger/OpenAPI 概念的混合。
资源是一个 REST 概念:“任何可能成为作者超文本引用目标的概念都必须符合资源的定义”
表示是一个 REST 概念:“表示是一个字节序列,加上用于描述这些字节的表示元数据。”
操作是一个 OpenAPI 概念:“OpenAPI 将唯一操作定义为路径和 HTTP 方法的组合。”
这里有一定程度的紧张,因为这些观点实际上并不相互一致。
例如,从 REST 的角度来看,没有理由记录“GET 操作”,因为 GET 是统一接口的一部分——无论使用什么值作为目标 uri,它都具有相同的语义。这是使万维网成为可能的关键架构约束的一部分——一致的语义意味着我们可以使用通用组件(如Web 浏览器)与 Web 上的所有不同资源进行交互。
不同表示形式的 Foo 资源实际上是“相同”资源还是不同的资源?
“这取决于”。
“一个资源,不同的表示”的一个经典例子是一张图片,我们可能有一个 GIF、JPEG、PNG、BMP。相同的图片(ish),但需要以不同方式处理的不同字节序列。
同样,您可能有一个网页 (HTML),还有一个文本/纯文本表示或 JSON 表示等。
要问的一个重要问题是:通用缓存是否具有为请求返回“正确”表示所需的信息?
也就是说:鉴于您的原始设计使用查询参数来区分一个投影与另一个投影,您应该尊重这种本能并继续将不同的表示视为属于不同的资源(这意味着通用缓存将使它们完全分开) .
这是否意味着您想要共享相同的路径 /foo(将投影视为可选的@ApiParam),或者为每个投影提供不同的路径(为每个唯一路径定义单独的操作)尚不清楚。在一个棕地项目中,我倾向于记录你已经拥有的东西,而不是进行大量的重大更改。
但是将“易于记录”视为设计约束当然是合理的。
推荐阅读
- css - 当高度缩小而不是div时css背景缩小
- python - Django 中的 URL 配置
- php - Laravel 的雄辩:不能编辑值
- excel - Excel2016:无法查询 PostgresSQL 数据库:不接受服务器证书
- amazon-elasticache - Terraform - Cloudwatch 警报 Elasticache 集群指标
- sql - SQLite:删除所有其余重复记录?
- machine-learning - 在 weka java 代码中使用平均概率投票
- c# - 从json字符串反序列化到字典列表?
- python - 是否可以将 spacy 与已经标记化的输入一起使用?
- html - 验证密码和用户名 nodejs mysql