代码之家  ›  专栏  ›  技术社区  ›  Swaroop C H

API版本控制的最佳实践?[闭门]

  •  878
  • Swaroop C H  · 技术社区  · 17 年前

    对于web服务REST API版本控制,是否有任何已知的how tos或最佳实践?

    AWS does versioning by the URL of the endpoint . 这是实现同一目标的唯一途径还是其他途径?如果有多种方法,每种方法的优点是什么?

    7 回复  |  直到 11 年前
        1
  •  682
  •   Luke Puplett    11 年前

    URI设计是 同时 RESTAPI最突出的部分和 对该API用户的长期承诺 .

    由于应用程序的演变,以及(在较小程度上)其API的演变是一个事实,它甚至类似于看似复杂的产品(如编程语言)的演变 URI设计 而且 . 应用程序和API的生命周期越长,对应用程序和API用户的承诺就越大。

    另一方面,生活中的另一个事实是,很难预见通过API消耗的所有资源及其方面。幸运的是,没有必要设计整个API,直到 Apocalypse . 正确定义所有资源端点以及每个资源和资源实例的寻址方案就足够了。

    此外,由于将API版本嵌入URI会破坏 hypermedia as the engine of application state (在Roy T.Fieldings博士论文中指出)通过拥有一个随时间变化的资源地址/URI,我可以得出以下结论: 意思是 .

    可以在基本URI中嵌入API版本 但是 仅用于合理和受限的用途,如调试API客户端

    关于维护有过期日期的API版本的一些想法。通常用于实现web服务的所有编程平台/语言(Java、.NET、PHP、Perl、Rails等)都允许轻松地将web服务端点绑定到基本URI。这样很容易理解 聚敛 文件/类/方法的集合 在不同的API版本之间进行分离

    从API用户的角度来看,当特定API版本如此明显时,使用和绑定该版本也更容易,但仅限于有限的时间,即在开发期间。

    从API维护者的观点来看,通过使用源代码控制系统(主要以文件为最小的(源代码)版本控制单元),可以更轻松地并行维护不同的API版本。

    API历史在URI设计中可见/不可见 因此,随着时间的推移,很容易发生变化 这违反了休息的准则。我同意!

    • 设计糟糕的API客户端 ).

    • 绑定到API的特定版本(变得明显),但仅在有限的时间内绑定

    http://shonzilla/api/customers/1234
    http://shonzilla/api/v3.0/customers/1234
    http://shonzilla/api/v3/customers/1234
    

    古老的 应通知API使用最新的先前API版本, . 因此,访问任何过时的URI如下:

    http://shonzilla/api/v2.2/customers/1234
    http://shonzilla/api/v2.0/customers/1234
    http://shonzilla/api/v2/customers/1234
    http://shonzilla/api/v1.1/customers/1234
    http://shonzilla/api/v1/customers/1234
    

    指示重定向的30个HTTP状态代码 Location HTTP头,重定向到资源URI的适当版本,该版本仍然是此版本:

    http://shonzilla/api/customers/1234
    

    至少有两个重定向HTTP状态代码适用于API版本控制方案:

        2
  •  273
  •   jeremyh    14 年前

    URL不应包含版本。该版本与您请求的资源的“想法”无关。您应该试着将URL看作是指向您想要的概念的路径,而不是您想要返回项目的方式。版本规定了对象的表示,而不是对象的概念。正如其他海报所说,您应该在请求头中指定格式(包括版本)。

    (BAD WAY TO DO IT):
    
    http://company.com/api/v3.0/customer/123
    ====>
    GET v3.0/customer/123 HTTP/1.1
    Accept: application/xml
    
    <====
    HTTP/1.1 200 OK
    Content-Type: application/xml
    <customer version="3.0">
      <name>Neil Armstrong</name>
    </customer>
    

    标题包含一行,该行包含您请求的表示形式(“Accept:application/xml”)。这就是版本应该去的地方。每个人似乎都在掩饰这样一个事实:你可能想要不同格式的同一件东西,客户应该能够要求它想要什么。在上面的例子中,客户要求 任何 资源的XML表示—实际上并不是它想要的真正表示。理论上,服务器可以返回与请求完全无关的内容,只要它是XML,并且必须对其进行解析才能意识到它是错误的。

    (GOOD WAY TO DO IT)
    
    http://company.com/api/customer/123
    ===>
    GET /customer/123 HTTP/1.1
    Accept: application/vnd.company.myapp.customer-v3+xml
    
    <===
    HTTP/1.1 200 OK
    Content-Type: application/vnd.company.myapp-v3+xml
    <customer>
      <name>Neil Armstrong</name>
    </customer>
    

    此外,假设客户机认为XML太冗长,现在他们想要JSON。在其他示例中,您必须为同一客户创建一个新的URL,因此您最终会得到:

    (BAD)
    http://company.com/api/JSONv3.0/customers/123
      or
    http://company.com/api/v3.0/customers/123?format="JSON"
    

    (或类似的东西)。实际上,每个HTTP请求都包含您要查找的格式:

    (GOOD WAY TO DO IT)
    ===>
    GET /customer/123 HTTP/1.1
    Accept: application/vnd.company.myapp.customer-v3+json
    
    <===
    HTTP/1.1 200 OK
    Content-Type: application/vnd.company.myapp-v3+json
    
    {"customer":
      {"name":"Neil Armstrong"}
    }
    

    使用这种方法,您在设计上有了更多的自由,并且实际上遵守了REST的原始想法。您可以在不中断客户端的情况下更改版本,也可以随着API的更改而增量更改客户端。如果选择停止支持表示,则可以使用HTTP状态代码或自定义代码响应请求。客户机还可以验证响应的格式是否正确,并验证XML。

    还有许多其他优势,我在我的博客上讨论了其中的一些优势: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html

    (Another reason why version in the URL sucks)
    http://company.com/api/v3.0/customer/123/v2.0/orders/4321/
    
        3
  •  98
  •   alex    13 年前

    我们发现把这个版本放在URL中是很实用的。它可以让你一眼就知道你在用什么。我们使用别名/foo to/foo/(最新版本),以便于使用,缩短/更清晰的URL,等等,正如公认的答案所示。

        4
  •  46
  •   Kevsy    14 年前

    我同意资源表示的版本控制更好地遵循REST方法……但是,自定义MIME类型(或附加版本参数的MIME类型)的一个大问题是对HTML和JavaScript中的“写入接受”和“内容类型”头的支持较差。

    例如,IMO不可能在HTML5表单中发布以下标题以创建资源:

    Accept: application/vnd.company.myapp-v3+json
    Content-Type: application/vnd.company.myapp-v3+json 
    

    enctype 属性是一个枚举,因此除了通常的 application/x-www-formurlencoded , multipart/form-data text/plain 无效。

    …我也不确定HTML4中的所有浏览器都支持它(HTML4具有更宽松的encytpe属性,但对于是否转发MIME类型,这将是浏览器实现的问题)

    正因为如此,我现在觉得最合适的版本发布方式是通过URI,但我承认这不是“正确”的方式。

        5
  •  21
  •   Sean O'Dell    13 年前

        6
  •  13
  •   pjz    14 年前

    有几个地方可以在REST API中进行版本控制:

    1. 如前所述,在URI中。如果重定向等被很好地使用,这可能是易于处理的,甚至是美观的。

    2. 在Accepts:标头中,因此版本位于文件类型中。比如“mp3”和“mp4”。这也会起作用,虽然在我看来,它不如。。。

    我可以看出使用这三种方法的原因:

    1. 如果您喜欢“清理”新的API,或者对于需要这种方法的主要版本更改。
    2. 如果您希望客户在执行PUT/POST之前知道它是否有效。
    3. 如果可以的话,如果客户必须执行PUT/POST来确定它是否有效。
        7
  •  8
  •   Alexander Torstling    12 年前

    最终,它就像其他API设计一样。权衡努力与客户便利。考虑为您的API采用语义版本化,这为您的客户清楚如何兼容新版本。