版本 REST URI 的最佳方式是什么?目前,我们在 URI 本身中有一个版本号,即。
http://example.com/users/v4/1234/
对于此表示的第 4 版。
版本是否属于查询字符串?IE。
http://example.com/users/1234?version=4
还是以另一种方式最好地完成版本控制?
版本 REST URI 的最佳方式是什么?目前,我们在 URI 本身中有一个版本号,即。
http://example.com/users/v4/1234/
对于此表示的第 4 版。
版本是否属于查询字符串?IE。
http://example.com/users/1234?version=4
还是以另一种方式最好地完成版本控制?
不要版本 URL,因为...
假设您的资源正在返回 application/vnd.yourcompany.user+xml 的某些变体,您需要做的就是创建对新的 application/vnd.yourcompany.userV2+xml 媒体类型的支持,并通过内容协商的魔力您的 v1 和v2 客户端可以和平共处。
在 RESTful 接口中,最接近合同的是定义在客户端和服务器之间交换的媒体类型。
客户端用来与服务器交互的 URL 应该由嵌入在先前检索到的表示中的服务器提供。客户端需要知道的唯一 URL 是接口的根 URL。仅当您在客户端上构建 url 时,向 url 添加版本号才有价值,您不应该使用 RESTful 接口来执行此操作。
如果您需要更改会破坏现有客户的媒体类型,请创建一个新客户并保留您的网址!
对于那些目前说如果我使用 application/xml 和 application/json 作为媒体类型的读者来说这是没有意义的。我们应该如何对它们进行版本控制?你不是。这些媒体类型对于 RESTful 接口几乎没有用,除非您使用代码下载来解析它们,此时版本控制是一个有争议的问题。
我想说让它成为 URI 本身的一部分(选项 1)是最好的,因为 v4 标识的资源与 v3 不同。第二个选项中的查询参数最好用于传入与请求相关的附加(查询)信息,而不是资源。
啊,我又要戴上我那顶脾气暴躁的旧帽子了。
从 ReST 的角度来看,这根本不重要。不是香肠。
客户端接收到它想要遵循的 URI,并将其视为不透明的字符串。将您想要的任何内容放入其中,客户端不知道其上的版本标识符之类的东西。
客户知道的是它可以处理媒体类型,我建议听从 Darrel 的建议。此外,我个人认为,需要将 restful 架构中使用的格式更改 4 次应该会带来巨大的警告信号,表明您正在做一些严重错误的事情,并且完全绕过了为更改弹性设计媒体类型的需要。
但无论哪种方式,客户端都只能处理具有它可以理解的格式的文档,并按照其中的链接进行操作。它应该知道链接关系(转换)。所以 URI 中的内容完全无关紧要。
我个人会投票给http://localhost/3f3405d5-5984-4683-bf26-aca186d21c04
一个完全有效的标识符,可以防止任何进一步的客户端开发人员或接触系统的人质疑是否应该将 v4 放在 URI 的开头或结尾(我建议,从服务器的角度来看,你不应该有 4版本,但有 4 种媒体类型)。
您不应该将版本放在 URL 中,而应该将版本放在请求的 Accept Header 中 - 请参阅我在此线程上的帖子:
如果您开始在 URL 中粘贴版本,您最终会得到如下愚蠢的 URL: http ://company.com/api/v3.0/customer/123/v2.0/orders/4321/
还有许多其他问题也在蔓延 - 请参阅我的博客: http ://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
这些(不太具体的)关于 REST API 版本控制的 SO 问题可能会有所帮助:
有 4 种不同的 API 版本控制方法:
将版本添加到 URI 路径:
http://example.com/api/v1/foo
http://example.com/api/v2/foo
当您有重大更改时,您必须增加版本,例如:v1、v2、v3...
你可以在你的代码中实现一个控制器,如下所示:
@RestController
public class FooVersioningController {
@GetMapping("v1/foo")
public FooV1 fooV1() {
return new FooV1("firstname lastname");
}
@GetMapping("v2/foo")
public FooV2 fooV2() {
return new FooV2(new Name("firstname", "lastname"));
}
请求参数版本控制:
http://example.com/api/v2/foo/param?version=1
http://example.com/api/v2/foo/param?version=2
version 参数可以是可选的,也可以是必需的,具体取决于您希望如何使用 API。
实现可能与此类似:
@GetMapping(value = "/foo/param", params = "version=1")
public FooV1 paramV1() {
return new FooV1("firstname lastname");
}
@GetMapping(value = "/foo/param", params = "version=2")
public FooV2 paramV2() {
return new FooV2(new Name("firstname", "lastname"));
}
传递自定义标头:
http://localhost:8080/foo/produces
带标题:
headers[Accept=application/vnd.company.app-v1+json]
或者:
headers[Accept=application/vnd.company.app-v2+json]
这种方案的最大优势主要是语义:您不会因为与版本控制有关的任何事情而使 URI 变得混乱。
可能的实现:
@GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
public FooV1 producesV1() {
return new FooV1("firstname lastname");
}
@GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
public FooV2 producesV2() {
return new FooV2(new Name("firstname", "lastname"));
}
更改主机名或使用 API 网关:
本质上,您是将 API 从一个主机名移动到另一个主机名。您甚至可以将其称为为相同资源构建新 API。
此外,您可以使用 API 网关执行此操作。
我想创建版本化的 API,我发现这篇文章非常有用:
http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
关于“我希望对我的 API 进行版本控制”有一小部分。我发现它简单易懂。关键是使用 header 中的 Accept 字段来传递版本信息。
如果 REST 服务需要在使用前进行身份验证,您可以轻松地将 API 密钥/令牌与 API 版本相关联并在内部进行路由。要使用新版本的 API,可能需要新的 API 密钥,并链接到该版本。
不幸的是,此解决方案仅适用于基于身份验证的 API。但是,它确实将版本保留在 URI 之外。
如果您使用 URI 进行版本控制,那么版本号应该在 API 根的 URI 中,因此每个资源标识符都可以包含它。
从技术上讲,REST API 不会因 URL 更改(统一接口约束的结果)而中断。只有当相关语义(例如特定于 API 的 RDF 词汇)以非向后兼容的方式(很少见)发生变化时,它才会中断。目前很多人不使用导航链接(HATEOAS 约束)和词汇来注释他们的 REST 响应(自我描述消息约束),这就是他们的客户中断的原因。
自定义 MIME 类型和 MIME 类型版本控制没有帮助,因为将相关元数据和表示的结构放入短字符串中不起作用。办公室。元数据和结构会经常更改,因此版本号也会...
因此,要回答您的问题,最好的方法是使用词汇(九头蛇,链接数据)注释您的请求和响应并忘记版本控制或仅通过非向后兼容的词汇更改使用它(例如,如果您想用另一个词汇替换一个词汇)。
我会将版本作为可选值包含在 URI 的末尾。这可以是 /V4 之类的后缀,也可以是您描述的查询参数。您甚至可以将 /V4 重定向到查询参数,以便支持这两种变体。
我投票赞成在 mime 类型中这样做,而不是在 URL 中。但原因和其他人不一样。
我认为用于定位唯一资源的 URL 应该是唯一的(那些重定向除外)。那么,如果您/v2.0
在 URL 中接受,为什么它不是/ver2.0
or /v2/
or /v2.0.0
?甚至-alpha
和-beta
?(然后它就完全变成了semver的概念)
因此,mime 类型的版本比 URL 更容易接受。