rest api版本_如何对REST API进行版本控制

rest api版本

If you're not very familiar with APIs, you might be wondering...why all the fuss about API versioning?

如果您对API不太熟悉,您可能会想...为什么对API版本控制大惊小怪?

If you've been burned by API changes, you're probably the one fussing. If you are a maintainer of an API, you might also be fussing about trying to field challenging questions like these:

如果您对API的更改感到厌倦,那么您可能会大惊小怪。 如果您是API的维护者,那么您可能还会大惊小怪地尝试解决诸如此类的难题:

# Is this version 2 of just products or of the entire API?
/v2/products

# What catalyzed the change between v1 and v2? How are they different?
/v1/products
/v2/products

These questions around versioning are not easy to answer. It's not always clear as to what v1 or v2 is referring to. And we should not just make a second version of an endpoint when the first no longer seems to suffice.

有关版本控制的这些问题不容易回答。 关于v1v2所指的并不总是很清楚。 而且,当第一个端点似乎不再足够时,我们不应该仅仅制作第二个端点。

There are clear reasons why your API needs to have versioning, and there are clear strategies for how to effectively navigate API changes.

为什么有你的API需要有版本明确的理由,并有对如何有效地导航API的变化明确的战略。

However, I have found that most developers--including myself, until I learned some lessons the hard way--are not aware of these reasons and strategies.

但是,我发现大多数开发人员,包括我自己,直到我以艰难的方式学到了一些教训之前,都没有意识到这些原因和策略。

This article seeks to highlight those reasons for versioning and strategies for accomplishing it. We're going to assume a REST API context, as it's a standard for many APIs, and focus on the versioning aspect.

本文旨在强调版本控制的原因以及实现版本控制的策略。 我们将假设REST API上下文,因为它是许多API的标准,并且将重点放在版本控制方面。

什么是版本控制? (What is Versioning?)

We should start with level-setting on what is meant by the term "API versioning". Here's our working definition:

我们应该从术语“ API版本控制”的级别设置开始。 这是我们的工作定义:

API versioning is the practice of transparently managing changes to your API.
API版本控制是透明管理API更改的做法。

Versioning is effective communication around changes to your API, so consumers know what to expect from it. You are delivering data to the public in some fashion and you need to communicate when you change the way that data is delivered.

版本控制是围绕API更改进行的有效沟通,因此,消费者知道可以从中获得什么。 您正在以某种方式向公众传递数据,并且在更改数据传递方式时需要进行沟通。

What this boils down to, in the nitty gritty, is managing data contracts and breaking changes. The former is the primary building block of your API and the latter reveals why versioning is needed.

归根结底,这就是管理数据合同和破坏变更。 前者是API的主要构建块,而后者则说明了为什么需要版本控制。

数据合约 (Data Contracts)

An API is an Application Programming Interface, and an interface is a shared boundary to exchange information. The data contract is the heart of this interface.

API是应用程序编程接口 ,而接口是交换信息的共享边界。 数据协定是此接口的核心。

A data contract is an agreement on the shape and general content of the request and/or response data.
数据合同是关于请求和/或响应数据的形状和一般内容的协议。

To illustrate a data contract, here's a basic JSON response body:

为了说明数据协定,这是一个基本的JSON响应主体:

{
  "data": [
    {
      "id": 1,
      "name": "Product 1"
    },
    {
      "id": 2,
      "name": "Product 2"
    }
  ]
}

It's an object with a data property that is an array (list) of products, each with an id and name property. But the data property could have just as easily been called body, and the id property on each product could have been a GUID instead of an integer. If a single product was being returned, data could be an object instead of an array.

它是一个对象,其data属性是产品的数组(列表),每个产品都有一个idname属性。 但是data属性可以很容易地称为body ,每个产品上的id属性可以是GUID而不是整数。 如果要返回单个产品,则data可以是对象而不是数组。

These seemingly subtle changes would have made for a different agreement, a different contract, regarding the "shape" of the data. The data shape could apply to property names, data types, or even the expected format (JSON vs. XML).

对于数据的“形状”,这些看似微妙的变化将导致不同的协议,不同的合同。 数据形状可以应用于属性名称,数据类型,甚至可以应用于期望的格式(JSON与XML)。

为什么需要版本控制? (Why is Versioning Needed?)

With APIs, something as simple as changing a property name from productId to productID can break things for consumers. This very thing happened to our team last week.

使用API​​,将属性名称从productId更改为productID可能很简单,可能productID消费者带来productID 。 上周这件事发生在我们的团队身上。

Thankfully, we had tests to catch changes to the API contract. However, we shouldn't have needed those tests, because the maintainers of the API should have known this would be a breaking change.

值得庆幸的是,我们进行了测试以捕获对API合同的更改。 但是,我们不应该需要这些测试,因为API的维护者应该知道这将是一个重大变化。

重大变化 (Breaking Changes)

This was a breaking change to the agreed upon data contract because their change forced us to change our application as well.

这是对约定的数据合同的重大更改,因为它们的更改也迫使我们也更改了应用程序。

What constitutes a "breaking change" in an API endpoint? Any change to your API contract that forces the consumer to also make a change.

什么是API端点中的“重大更改”? 您对API合同的任何更改都迫使消费者也必须进行更改。

Breaking changes primarily fit into the following categories:

重大更改主要包括以下几类:

  1. Changing the request/response format (e.g. from XML to JSON)

    更改请求/响应格式(例如,从XML更改为JSON)
  2. Changing a property name (e.g. from name to productName) or data type on a property (e.g. from an integer to a float)

    更改属性名称(例如,从name更改为productName )或更改属性的数据类型(例如,从整数更改为浮点数)

  3. Adding a required field on the request (e.g. a new required header or property in a request body)

    在请求上添加必填字段(例如,请求正文中新的必填标头或属性)
  4. Removing a property on the response (e.g. removing description from a product)

    删除响应中的属性(例如,删除产品description )

API变更管理 (API Change Management)

It is never wise or kind to force consumers of an API to make a change. If you must make a breaking change, that's what versioning is for, and we'll cover the most effective ways to version your application and endpoints.

强迫API使用者进行更改永远是不明智的选择。 如果您必须进行重大更改,那就是版本控制的目的,我们将介绍对应用程序和端点进行版本控制的最有效方法。

But first let's briefly discuss how to avoid breaking changes in the first place. We could call this API change management.

但是首先让我们简要地讨论一下如何避免破坏更改。 我们可以称之为API变更管理。

Effective change management in the context of an API is summarized by the following principles:

以下原则总结了API上下文中的有效变更管理:

  • Continue support for existing properties/endpoints

    继续支持现有的属性/端点
  • Add new properties/endpoints rather than changing existing ones

    添加新的属性/端点,而不是更改现有属性/端点
  • Thoughtfully sunset obsolete properties/endpoints

    考虑周到的日落过时属性/端点

Here's an example that demonstrates all three of these principles in the context of the response for requesting user data:

这是一个示例,它在请求用户数据的响应上下文中展示了所有这三个原理:

{
  "data": {
    "id": 1,
    "name": "Carlos Ray Norris",     // original property
    "firstName": "Carlos",           // new property
    "lastName": "Norris",            // new property
    "alias": "Chuck",                // obsolete property
    "aliases": ["Chuck", "Walker"]   // new property
  },
  "meta": {
    "fieldNotes": [
      {
        "field": "alias",
        "note": "Sunsetting on [future date]. Please use aliases."
      }
    ]
  }
}

In this example, name was an original property. The firstName and lastName fields are being implemented to provide a more granular option, in the event that the consumer wants to display "Mr. Norris" with some string interpolation but without having to parse the name field. However, the name property will be supported in an ongoing fashion.

在此示例中, name是原始属性。 如果消费者希望通过一些字符串插值显示“ Norris先生”而不必解析name字段,则将firstNamelastName字段实现为提供更精细的选项。 但是,将持续支持name属性。

alias, on the other hand, is going to be deprecated in favor of the aliases array--because Chuck has so many aliases--and there is a note in the response to indicate the sunsetting time frame.

alias ,而另一方面,会赞成的被弃用aliases阵列-因为查有如此多的别名-并且在响应指示落霞时间框架的说明。

您如何版本化API? (How Do You Version an API?)

These principles will take a long way in navigating changes to your API without needing to roll a new version. However, sometimes it's avoidable, and if you need a brand new data contract, you'll need a new version of your endpoint. So you'll need to communicate that to the public in some way.

在无需更改新版本的情况下,在浏览对API的更改时,这些原则将花费很长的时间。 但是,有时这是可以避免的,并且如果您需要全新的数据合同,则需要新版本的端点。 因此,您需要以某种方式将其传达给公众。

As an aside, do note that we're not talking about the version of the underlying code base. So if you're using semantic versioning for your application that also supports a public API, you will likely want to separate those versioning systems.

顺便说一句,请注意,我们并不是在谈论基础代码库的版本。 因此,如果您正在为还支持公共API的应用程序使用语义版本控制 ,则可能需要将这些版本控制系统分开。

How do you create a new version of your API? What are the different methods for doing so? You'll need to determine what type of versioning strategy you want to take in general, and then as you develop and maintain your API, you'll need to determine the scope of each version change.

您如何创建API的新版本? 这样做有哪些不同的方法? 您需要确定总体上要采用哪种类型的版本控制策略,然后在开发和维护API时,需要确定每个版本更改的范围

范围 (Scope)

Let's tackle scope first. As we explored above, sometimes data contracts will be compromised by a breaking change, and that means we'll need to provide a new version of the data contract. That could mean a new version of an endpoint, or it could mean a change at a more global application scope.

让我们先解决范围。 正如我们在上面探讨的那样,有时数据合约会因重大更改而受到损害,这意味着我们需要提供新版本的数据合约。 这可能意味着端点的新版本,或者可能意味着在更全局的应用程序范围内进行了更改。

We can think of levels of scope change within a tree analogy:

我们可以在树的类比中考虑范围变化的级别:

  • Leaf - A change to an isolated endpoint with no relationship to other endpoints

    叶子 -更改为隔离的端点,与其他端点没有关系

  • Branch - A change to a group of endpoints or a resource accessed through several endpoints

    分支 -更改为一组端点或通过多个端点访问的资源

  • Trunk - An application-level change, warranting a version change on most or all endpoints

    中继线 -应用程序级更改,保证大多数或所有端点上的版本更改

  • Root - A change affecting access to all API resources of all versions

    -更改影响对所有版本的所有API资源的访问

As you can see, moving from leaf to root, the changes become progressively more impactful and global in scope.

如您所见,从叶到根,这些更改变得越来越有影响力,并且范围越来越广。

The leaf scope can often be handled through effective API change management. If not, simply create a new endpoint with the new resource data contract.

叶子范围通常可以通过有效的API更改管理进行处理。 如果没有,只需使用新的资源数据协定创建一个新的端点。

A branch is a little trickier, depending on just how many endpoints are affected by the data contract change on the resource in question. If the changes are relatively confined to a clear group of related endpoints, you could potentially navigate this by introducing a new name for the resource and updating your docs accordingly.

分支有点棘手,具体取决于有多少资源受相关资源上的数据协定更改影响。 如果更改相对仅限于一组清晰的相关端点,则可以通过为资源引入新名称并相应地更新文档来进行导航。

# variants, which has a breaking change, is accessed on multiple routes
/variants
/products/:id/variants

# we introduce product-variants instead
/product-variants
/products/:id/product-variants

A trunk refers to application-level changes that are often a result of a change in one of the following categories:

干线是指应用程序级更改,这些更改通常是以下类别之一更改的结果:

  • Format (e.g. from XML to JSON)

    格式(例如,从XMLJSON )

  • Specification (e.g. from an in-house one to JSON API or Open API)

    规范(例如,从内部到JSON APIOpen API )

  • Required headers (e.g. for authentication/authorization)

    必需的标题(例如,用于身份验证/授权)

These will necessitate a change in your overall API version, so you should plan carefully and execute the transition well.

这些将需要更改整个API版本,因此您应该仔细计划并正确执行过渡。

A root change will force you to go one step further in ensuring that all consumers of all versions of your API are aware of the change.

根本更改将迫使您更进一步,以确保所有版本的API的所有使用者都知道该更改。

API版本控制的类型 (Types of API Versioning)

As we turn to different types of API versioning, we'll want to use these insights into varying scopes of API changes to evaluate the types. Each approach has its own set of strengths and weaknesses in addressing changes based on their scope.

当我们转向不同类型的API版本控制时,我们将希望利用这些见解对API更改的不同范围进行评估。 每种方法在根据其范围来解决更改时都有其优点和缺点。

There are several methods for managing the version of your API. URI path versioning is the most common.

有几种方法可以管理您的API版本。 URI路径版本控制是最常见的。

URI路径 (URI Path)

http://www.example.com/api/v1/products
http://api.example.com/v1/products

This strategy involves putting the version number in the path of the URI, and is often done with the prefix "v". More often than not, API designers use it to refer to their application version (i.e. "trunk") rather than the endpoint version (i.e. "leaf" or "branch"), but that's not always a safe assumption.

此策略涉及将版本号放在URI的路径中,并且通常使用前缀“ v”来完成。 API设计人员经常使用它来引用其应用程序版本(即“ trunk”),而不是端点版本(即“ leaf”或“ branch”),但这并不是一个安全的假设。

URI path versioning implies orchestrated releases of application versions that will require one of two approaches: maintaining one version while developing a new one or forcing consumers to wait for new resources until the new version is released. It also means you'd need to carry over any non-changed endpoints from version to version. However, for APIs with relatively low volatility, it's still a decent option.

URI路径版本化意味着应用程序版本的协调发行,这将需要以下两种方法之一:在开发新版本时维护一个版本,或强迫使用者等待新资源,直到新版本发布为止。 这也意味着您需要将所有未更改的端点从一个版本移植到另一个版本。 但是,对于挥发性相对较低的API,它仍然是不错的选择。

You would likely not want to relate your version number to that of the endpoint or resource, because it would easily result in something like a v4 of products but a v1 of variants, which would be rather confusing.

您可能不希望将版本号与端点或资源的版本号相关联,因为它很容易导致产生products v4variants v1的问题,这会造成混乱。

查询参数 (Query Params)

http://www.example.com/api/products?version=1

This type of versioning adds a query param to the request that indicates the version. Very flexible in terms of requesting the version of the resource you'd like at the "leaf" level, but it holds no notion of the overall API's version and lends itself to the same out-of-sync issues mentioned in the above comment on endpoint-level versioning of the URI path.

这种类型的版本控制将查询参数添加到指示版本的请求中。 在“叶子”级别上请求所需资源的版本方面非常灵活,但是它不包含整个API版本的概念,并且使其本身具有上述注释中提到的不同步问题URI路径的端点级别版本控制。

Accept: version=1.0

The header approach is one that provides more granularity in serving up the requested version of any given resource.

标头方法是一种在提供任何给定资源的请求版本时提供更细粒度的方法。

However, it's buried in the request object and isn't as transparent as the URI path option. It's also still hard to tell whether 1.0 refers to the version of the endpoint or the API itself.

但是,它埋在请求对象中,并且不像URI路径选项那样透明。 仍然很难确定1.0是指端点的版本还是API本身。

整合类型 (Integrating Types)

Each of these approaches seem to have the weakness of either favoring a "leaf" or "trunk" scope, but not supporting both.

这些方法中的每一个似乎都有缺点,要么偏爱“叶子”范围,要么偏爱“树干”范围,但不支持两者。

If you need to maintain the overall API version and also provide support for multiple versions of resources, consider a blend of the URI Path and Query Params types, or a more advanced Header approach.

如果您需要维护整个API版本,并且还提供对多种资源版本的支持,请考虑URI路径和查询参数类型的混合,或者使用更高级的标头方法。

# URI path and query params combo
http://api.example.com/v1/products?version=1
http://api.example.com/v1/products?version=2

# Extended headers, for http://api.example.com/products
Accept: api-version=1; resource-version=1
Accept: api-version=1; resource-version=2

结论 (Conclusion)

We've covered a lot of ground here, so let's recap:

我们在这里介绍了很多内容,因此让我们回顾一下:

  • API versioning is the practice of transparently managing changes to your API.

    API版本控制是透明管理API更改的做法。
  • Managing an API boils down to defining and evolving data contracts and dealing with breaking changes.

    管理API归结为定义和发展数据合同以及处理重大更改。
  • The most effective way to evolve your API without breaking changes is to follow effective API change management principles.

    在不破坏更改的情况下发展API的最有效方法是遵循有效的API更改管理原则。
  • For most APIs, versioning in the URI path is the most straightforward solution.

    对于大多数API,URI路径中的版本控制是最简单的解决方案。
  • For more complex or volatile APIs, you can manage varying scopes of changes by employing an integration of URI path and query params approaches.

    对于更复杂或易失的API,您可以通过采用URI路径和查询参数方法的集成来管理变化范围。

Although these principles should provide clear direction in how to effectively manage change to your APIs, evolving an API is potentially more of an art than a science. It requires thought and foresight to create and maintain a reliable API.

尽管这些原则应为如何有效管理API更改提供明确的指导,但发展API可能是一门艺术,而不是一门科学。 创建和维护可靠的API需要思想和远见。

翻译自: https://www.freecodecamp.org/news/how-to-version-a-rest-api/

rest api版本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值