首页 > 解决方案 > 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另一个不接受。

但是,根据(当前)@ApiOperationSwagger 注释,我选择了错误的 API 设计。

HTTP 方法和路径的组合创建了唯一的操作

因此,在我将旧项目升级到当前库版本后,Swagger 模型只包含一个GET /foo操作——这是随机的,因为它依赖于通过 Java 反射进行的运行时代码自省。

所以,问题是这样的:不同表示Foo的资源实际上是“相同”资源还是不同的资源?Swagger 注释似乎暗示了后者(不同的资源-> 不同的路径)。

标签: restswaggerjax-rsopenapi

解决方案


您遇到的部分问题是 REST 概念和 Swagger/OpenAPI 概念的混合。

资源是一个 REST 概念:“任何可能成为作者超文本引用目标的概念都必须符合资源的定义”

表示是一个 REST 概念:“表示是一个字节序列,加上用于描述这些字节的表示元数据。”

操作是一个 OpenAPI 概念:“OpenAPI 将唯一操作定义为路径和 HTTP 方法的组合。”

这里有一定程度的紧张,因为这些观点实际上并不相互一致。

例如,从 REST 的角度来看,没有理由记录“GET 操作”,因为 GET 是统一接口的一部分——无论使用什么值作为目标 uri,它都具有相同的语义。这是使万维网成为可能的关键架构约束的一部分——一致的语义意味着我们可以使用通用组件(如Web 浏览器)与 Web 上的所有不同资源进行交互。


不同表示形式的 Foo 资源实际上是“相同”资源还是不同的资源?

“这取决于”。

“一个资源,不同的表示”的一个经典例子是一张图片,我们可能有一个 GIF、JPEG、PNG、BMP。相同的图片(ish),但需要以不同方式处理的不同字节序列。

同样,您可能有一个网页 (HTML),还有一个文本/纯文本表示或 JSON 表示等。

要问的一个重要问题是:通用缓存是否具有为请求返回“正确”表示所需的信息?

也就是说:鉴于您的原始设计使用查询参数来区分一个投影与另一个投影,您应该尊重这种本能并继续将不同的表示视为属于不同的资源(这意味着通用缓存将使它们完全分开) .

这是否意味着您想要共享相同的路径 /foo(将投影视为可选的@ApiParam),或者为每个投影提供不同的路径(为每个唯一路径定义单独的操作)尚不清楚。在一个棕地项目中,我倾向于记录你已经拥有的东西,而不是进行大量的重大更改。

但是将“易于记录”视为设计约束当然是合理的。


推荐阅读