版本REST API [英] Versioning REST API

查看:205
本文介绍了版本REST API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在看过REST的版本了大量的材料后,我thnking版本的调用,而不是API的。例如:

After having read a lot of material on REST versioning, I am thnking of versioning the calls instead of the API. For example:

http://api.mydomain.com/callfoo/v2.0/param1/param2/param3
http://api.mydomain.com/verifyfoo/v1.0/param1/param2

,而不是先吃点

http://api.mydomain.com/v1.0/callfoo/param1/param2
http://api.mydomain.com/v1.0/verifyfoo/param1/param2

然后将

http://api.mydomain.com/v2.0/callfoo/param1/param2/param3
http://api.mydomain.com/v2.0/verifyfoo/param1/param2

好处我看到的是:

The advantage I see are:


  • 当来电更改,我不必重写我的整个客户端 - 仅由更改电话影响了部分

  • 的工作好可以继续为客户端的那些部分(我们有很多的投入测试小时,以保证客户端和服务器两侧是稳定的。)

  • 我可以使用永久或非永久重定向已更改来电。

  • 向后兼容性将是一件轻而易举的事,因为我可以离开旧的通话版本不变。

我失去了财产以后?请指教。

Am I missing somthing? Please advise.

推荐答案

需要的HTTP标头。

版本:1

借助版本头临时注册中的 RFC 4229 ,并有一些正当理由,以避免使用X- preFIX或特定用途-URI。更典型的头球攻门被提出的 yfeldblum 是在 http://stackoverflow.com/a/2028664

The Version header is provisionally registered in RFC 4229 and there some legitimate reasons to avoid using an X- prefix or a usage-specific URI. A more typical header was proposed by yfeldblum at http://stackoverflow.com/a/2028664:

X-API的版本:1

在这两种情况下,如果头缺少或不匹配的服务器可以提供,发送一个 412 $ P $失败pcondition $回应与失败的原因沿C $ C 。这就要求客户指定他们支持每一次的版本,但强制执行客户端和服务器之间的一致响应。 (可选支持?版本= 查询参数会给客户的灵活性,额外位)。

In either case, if the header is missing or doesn't match what the server can deliver, send a 412 Precondition Failed response code along with the reason for the failure. This requires clients to specify the version they support every single time but enforces consistent responses between client and server. (Optionally supporting a ?version= query parameter would give clients an extra bit of flexibility.)

这方法简单,容易实现,符合标准。

This approach is simple, easy to implement and standards-compliant.

我知道,一些非常聪明,好心人建议URL版本和内容协商。两人都在某些情况下,并在它们通常建议的形式显著的问题。

I'm aware that some very smart, well-intentioned people have suggested URL versioning and content negotiation. Both have significant problems in certain cases and in the form that they're usually proposed.

如果你控制所有服务器和客户端端点/服务URL版本的作品。否则,你需要处理更新的客户端回落到旧的服务器,你会拥有自定义HTTP头做,因为部署在你的控制范围之外的异构服务器服务器软件的系统管理员可以做各种事情搞砸了你认为的URL会很容易,如果你使用类似临时移动 302

Endpoint/service URL versioning works if you control all servers and clients. Otherwise, you'll need to handle newer clients falling back to older servers, which you'll end up doing with custom HTTP headers because system administrators of server software deployed on heterogeneous servers outside of your control can do all sorts of things to screw up the URLs you think will be easy to parse if you use something like 302 Moved Temporarily.

如果你是深切关注以下HTTP标准,而且要忽略哪些HTTP / 1.1标准的文件居然说通过接受头内容协商工作。您往往会看到建议的MIME类型的形式应用程序/ vnd.example.v1 + JSON 的东西。有几个问题:

Content negotiation via the Accept header works if you are deeply concerned about following the HTTP standard but also want to ignore what the HTTP/1.1 standard documents actually say. The proposed MIME Type you tend to see is something of the form application/vnd.example.v1+json. There are a few problems:


  1. 有那里的供应商扩展实际上是合适的,当然病例,但客户端和服务器之间略有不同的传播行为并不真正适合一个新的媒体类型的定义。此外, RFC 2616(HTTP / 1.1)写着的媒体类型的值与注册互联网号码分配机构,媒体类型登记过程在RFC 1590使用非注册的媒体类型是不鼓励的概述。的,我不希望看到一个独立的媒体类型为每个软件产品的每个版本具有REST API。

  2. 任何亚型范围(例如,应用程序/ * )没有任何意义。对于REST的API结构化数据返回给客户端处理和格式化,有什么好正在接受 * / *

  3. 接受头需要一些努力正确解析。有两个隐含的和明确的precedence应遵循尽量减少实际上正确地做内容协商所需的背和反复。如果您很在意正确实施本标准,这是重要的是得到正确的。

  4. RFC 2616(HTTP / 1.1)描述为不包括接受标题:。如果没有接受头域present,则假定客户端接受所有媒体类型的所以,为客户你不未写自己(在这里你有最少的控制),做最正确的事情将是使用最新的,最容易对破老版本版本服务器知道响应请求。换句话说,就可能不是在所有实施版本管理和这些客户端仍会以完全相同的方式来打破。

  1. There are cases where the vendor extensions are actually appropriate, of course, but slightly different communication behaviors between client and server doesn't really fit the definition of a new 'media type'. Also, RFC 2616 (HTTP/1.1) reads, "Media-type values are registered with the Internet Assigned Number Authority. The media type registration process is outlined in RFC 1590. Use of non-registered media types is discouraged." I don't want to see a separate media type for every version of every software product that has a REST API.
  2. Any subtype ranges (e.g., application/*) don't make sense. For REST APIs that return structured data to clients for processing and formatting, what good is accepting */* ?
  3. The Accept header takes some effort to parse correctly. There's both an implied and explicit precedence that should be followed to minimize the back-and-forth required to actually do content negotiation correctly. If you're concerned about implementing this standard correctly, this is important to get right.
  4. RFC 2616 (HTTP/1.1) describes the behavior for any client that does not include an Accept header: "If no Accept header field is present, then it is assumed that the client accepts all media types." So, for clients you don't write yourself (where you have the least control), the most correct thing to do would be to respond to requests using the newest, most prone-to-breaking-old-versions version that the server knows about. In other words, you could have not implemented versioning at all and those clients would still be breaking in exactly the same way.

主编,2014年

我已经读了很多其他的答案,大家的深思熟虑的意见的;我希望我能改善这与几年反馈的好处:

I've read a lot of the other answers and everyone's thoughtful comments; I hope I can improve on this with the benefit of a couple of years of feedback:


  1. 不要使用'X-'preFIX 。我觉得接受-版本大概是在2014年更有意义,而且大约有重复使用版本提出了意见。有伴的定义标题是重叠的,比如内容版本和URI肯定的相对不透明,我努力要小心内容的谈判与变化混淆这两种,其中版本头是有效。网址 https://example.com/api/212315c2-668d-11e4-80c7-20c9d048772b 的第三个'版本'是比'第二'完全不同,无论它是否包含数据或文档。

  2. 对于我上面所说的关于URL的版本说(如 https://example.com/v1/users 端点,例如)反之很可能拥有更多的道理:如果你控制所有服务器和客户端,URL / URI的版本可能是你想要的东西。对于一个大型的服务,可以发布一个服务URL,我会去与不同的端点为每个版本的最喜欢做的。我特别采取的是严重的事实,上述的实现是由许多不同组织的最常用部署在许多不同的服务器上,而且,也许最重要的是,在服务器上我无法控制的影响。我总是想规范服务的URL,如果一个网站仍在运行的API V3版本,我绝对不希望 https://example.com/v4/ 回来与他们的网络服务器的 404未找​​到的网页(或更糟的是, 200 OK 的返回他们的主页作为蜂窝数据的HTML 500K回到一个iPhone应用程序。)

  3. 如果你想很简单/客户/实现(和更广泛地采用),这是很难认为需要在HTTP请求自定义标题是用于客户端的作者为 GET -ting香草URL。 (虽然认证通常需要你的令牌或凭据的头信息中传递,无论如何。使用版本接受-版本沿带的实际的秘密握手适合pretty还有一个秘密的握手。)

  4. 使用内容协商的接受头是好的获取不同的MIME类型相同的内容(例如,XML与JSON对比的Adobe PDF),而不是定义这些事情的版本(都柏林核心1.1与JSONP与PDF / A)。如果你想支持接受头,因为它尊重的行业标准是非常重要的,那么你就不会想要一个虚构的MIME类型,你可能需要媒体类型协商干扰在请求中使用。一个定制的API版本头保证不会与大量使用的,经常被引用的接受,而混为一谈他们到相同的使用只会被混淆为服务器和客户端干扰。这就是说,你的命名空间预计到2013每的 RFC6906 名为轮廓是什么preferable到一个单独报头的地段的原因。这是pretty聪明,和我认为人们应该认真考虑这种做法

  5. 添加标题为每个请求是一个特别的缺点一种无状态协议内工作。

  6. 恶意代理服务器可以做几乎任何事情破坏HTTP请求和响应。 他们不应该的,虽然我不'T谈谈缓存控制或的因人而异头在这种情况下,所有服务的创造者应该认真考虑他们的内容是如何在许多不同的环境中消耗掉。

  1. Don't use an 'X-' prefix. I think Accept-Version is probably more meaningful in 2014, and there are some valid concerns about the semantics of re-using Version raised in the comments. There's overlap with defined headers like Content-Version and the relative opaqueness of the URI for sure, and I try to be careful about confusing the two with variations on content negotiation, which the Version header effectively is. The third 'version' of the URL https://example.com/api/212315c2-668d-11e4-80c7-20c9d048772b is wholly different than the 'second', regardless of whether it contains data or a document.
  2. Regarding what I said above about URL versioning (endpoints like https://example.com/v1/users, for instance) the converse probably holds more truth: if you control all servers and clients, URL/URI versioning is probably what you want. For a large-scale service that could publish a single service URL, I would go with a different endpoint for every version, like most do. My particular take is heavily influenced by the fact that the implementation as described above is most commonly deployed on lots of different servers by lots of different organizations, and, perhaps most importantly, on servers I don't control. I always want a canonical service URL, and if a site is still running the v3 version of the API, I definitely don't want a request to https://example.com/v4/ to come back with their web server's 404 Not Found page (or even worse, 200 OK that returns their homepage as 500k of HTML over cellular data back to an iPhone app.)
  3. If you want very simple /client/ implementations (and wider adoption), it's very hard to argue that requiring a custom header in the HTTP request is as simple for client authors as GET-ting a vanilla URL. (Although authentication often requires your token or credentials to be passed in the headers, anyway. Using Version or Accept-Version as a secret handshake along with an actual secret handshake fits pretty well.)
  4. Content negotiation using the Accept header is good for getting different MIME types for the same content (e.g., XML vs. JSON vs. Adobe PDF), but not defined for versions of those things (Dublin Core 1.1 vs. JSONP vs. PDF/A). If you want to support the Accept header because it's important to respect industry standards, then you won't want a made-up MIME Type interfering with the media type negotiation you might need to use in your requests. A bespoke API version header is guaranteed not to interfere with the heavily-used, oft-cited Accept, whereas conflating them into the same usage will just be confusing for both server and client. That said, namespacing what you expect into a named profile per 2013's RFC6906 is preferable to a separate header for lots of reasons. This is pretty clever, and I think people should seriously consider this approach.
  5. Adding a header for every request is one particular downside to working within a stateless protocol.
  6. Malicious proxy servers can do almost anything to destroy HTTP requests and responses. They shouldn't, and while I don't talk about the Cache-Control or Vary headers in this context, all service creators should carefully consider how their content is consumed in lots of different environments.

这篇关于版本REST API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆