天天看點

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.

有關版本控制的這些問題不容易回答。 關于

v1

v2

所指的并不總是很清楚。 而且,當第一個端點似乎不再足夠時,我們不應該僅僅制作第二個端點。

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

屬性是産品的數組(清單),每個産品都有一個

id

name

屬性。 但是

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

字段,則将

firstName

lastName

字段實作為提供更精細的選項。 但是,将持續支援

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)

    格式(例如,從XML到JSON )

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

    規範(例如,從内部到JSON API或Open 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

v4

variants

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路徑的端點級别版本控制。

标頭 (Header)

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版本