877

Web サービス REST API のバージョン管理に関する既知のハウツーやベスト プラクティスはありますか?

AWS はエンドポイントの URL によってバージョン管理を行っていることに気付きました。これが唯一の方法ですか、それとも同じ目標を達成するための他の方法はありますか? 複数の方法がある場合、それぞれの方法のメリットは何ですか?

4

7 に答える 7

682

これは良い質問であり、難しい質問です。URI設計のトピックは、同時にREST APIの最も重要な部分であり、したがって、そのAPIのユーザーに対する潜在的に長期的な取り組みです。

アプリケーションの進化と、程度は少ないがそのAPIは現実のものであり、プログラミング言語のような一見複雑な製品の進化にも似ているため、URI設計には自然な制約が少なく、保存する必要があります。時間の経過とともに。アプリケーションとAPIの寿命が長いほど、アプリケーションとAPIのユーザーへのコミットメントが大きくなります。

一方、もう1つの現実は、APIを介して消費されるすべてのリソースとその側面を予測するのは難しいということです。幸い、 Apocalypseまで使用されるAPI全体を設計する必要はありません。すべてのリソースエンドポイントと、すべてのリソースおよびリソースインスタンスのアドレス指定スキームを正しく定義するだけで十分です。

時間の経過とともに、特定のリソースごとに新しいリソースと新しい属性を追加する必要がありますが、APIユーザーが特定のリソースにアクセスするために従う方法は、リソースアドレス指定スキームが公開されて最終的になった後は変更しないでください。

このメソッドは、HTTP動詞セマンティクス(たとえば、PUTは常に更新/置換する必要があります)および以前のAPIバージョンでサポートされているHTTPステータスコード(人間の介入なしで機能したAPIクライアントが機能し続けることができるように機能し続ける必要があります)に適用されますそのように)。

さらに、APIバージョンをURIに埋め込むと、時間の経過とともに変化するリソースアドレス/ URIを持つことで、アプリケーション状態のエンジンとしてのハイパーメディアの概念(Roy T. Fieldings PhDの論文に記載)が混乱するため、APIはバージョンをリソースURIに長期間保持しないでください。つまり、APIユーザーが依存できるリソースURIはパーマリンクである必要があります

もちろん、APIバージョンをベースURIに埋め込むことは可能ですが、新しいAPIバージョンで動作するAPIクライアントのデバッグなど、合理的で制限された用途にのみ使用できます。このようなバージョン管理されたAPIは、時間制限があり、APIユーザーの限られたグループ(クローズドベータ版など)のみが利用できるようにする必要があります。そうでなければ、あなたはすべきでないところに自分自身をコミットします。

有効期限のあるAPIバージョンのメンテナンスに関するいくつかの考え。Webサービス(Java、.NET、PHP、Perl、Railsなど)の実装に一般的に使用されるすべてのプログラミングプラットフォーム/言語により、WebサービスのエンドポイントをベースURIに簡単にバインドできます。このようにして、ファイル/クラス/メソッドのコレクションを簡単に収集して、異なるAPIバージョン間で分離しておくことができます。

APIユーザーのPOVからは、特定のAPIバージョンを操作してバインドするのも簡単です。これは明らかですが、限られた時間、つまり開発中だけです。

APIメンテナのPOVから、(ソースコード)バージョニングの最小単位として主にファイルで機能するソース管理システムを使用することで、さまざまなAPIバージョンを並行して維持することが容易になります。

ただし、APIバージョンがURIで明確に表示される場合は、注意が必要です。API履歴がURI設計で表示/表示されるように なり、RESTのガイドラインに反する時間の経過とともに変更される傾向があるため、このアプローチに反対する場合もあります。同意します!

この合理的な反対意見を回避する方法は、バージョンレスAPIベースURIで最新のAPIバージョンを実装することです。この場合、APIクライアント開発者は次のいずれかを選択できます。

  • 最新のものに対して開発します(不適切に設計されたAPIクライアントを破壊する可能性のある最終的なAPI変更からアプリケーションを保護するためにアプリケーションを維持することを約束します)。

  • APIの特定のバージョンにバインドします(これは明らかになります)が、限られた時間だけです

たとえば、API v3.0が最新のAPIバージョンである場合、次の2つはエイリアスである必要があります(つまり、すべてのAPIリクエストと同じように動作します)。

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

さらに、古いAPIをポイントしようとするAPIクライアントは、使用しているAPIバージョンが廃止されているか、サポートされなくなった場合は、最新の以前のAPIバージョンを使用するように通知する必要があります。したがって、次のような廃止されたU​​RIのいずれかにアクセスします。

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

リソースURIの適切なバージョンにリダイレクトするHTTPヘッダーと組み合わせて使用​​されるリダイレクトを示す30xHTTPステータスコードのいずれかを返す必要があります。Location

http:// shonzilla / api / customers / 1234

APIバージョニングシナリオに適したリダイレクトHTTPステータスコードは少なくとも2つあります。

  • 301永続的に移動されました。これは、要求されたURIを持つリソースが永続的に別のURIに移動されることを示します(APIバージョン情報を含まないリソースインスタンスのパーマリンクである必要があります)。このステータスコードを使用して、廃止された/サポートされていないAPIバージョンを示し、バージョン管理されたリソースURIがリソースパーマリンクに置き換えられたことをAPIクライアントに通知できます。

  • 302要求されたリソースが一時的に別の場所にあることを示していますが、要求されたURIは引き続きサポートされている可能性があります。このステータスコードは、バージョンのないURIが一時的に利用できず、リダイレクトアドレスを使用してリクエストを繰り返す必要があり(たとえば、APiバージョンが埋め込まれたURIを指す)、クライアントにそれを使用し続けるように指示する場合に役立ちます(つまり、パーマリンク)。

  • 他のシナリオは、HTTP1.1仕様のリダイレクト3xxの章にあります。

于 2008-12-29T20:24:36.380 に答える
273

URL にバージョンを含めないでください。バージョンは、リクエストしているリソースの「アイデア」とは何の関係もありません。URL は、アイテムを返す方法ではなく、目的のコンセプトへのパスであると考える必要があります。バージョンは、オブジェクトの概念ではなく、オブジェクトの表現を指示します。他の投稿者が言っているように、リクエスト ヘッダーで形式 (バージョンを含む) を指定する必要があります。

バージョンを持つ URL の完全な HTTP 要求を見ると、次のようになります。

(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

URL にバージョンを入れることがいかに悪いかを示す最後の例です。オブジェクト内の情報が必要で、さまざまなオブジェクトをバージョン管理したとします (顧客は v3.0、注文は v2.0、shipto オブジェクトは v4.2)。クライアントで指定する必要がある厄介な URL は次のとおりです。

(Another reason why version in the URL sucks)
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/
于 2011-07-19T16:08:50.557 に答える
98

URL にバージョンを入れると実用的で便利であることがわかりました。何を使っているか一目で分かります。受け入れられた回答が示唆するように、使いやすさ、より短い/よりクリーンなURLなどのために、 /foo を /foo/(最新バージョン) にエイリアスします。

下位互換性を永久に維持することは、多くの場合、法外な費用がかかり、かつ/または非常に困難です。非推奨、ここで提案されているようなリダイレクト、ドキュメント、およびその他のメカニズムについては、事前に通知することをお勧めします。

于 2011-01-04T20:57:12.390 に答える
46

リソース表現のバージョン管理はRESTアプローチに従うことに同意します...しかし、カスタムMIMEタイプ(またはバージョンパラメーターを追加するMIMEタイプ)の大きな問題の1つは、HTMLおよびContent-Typeヘッダーへの書き込みのサポートが不十分なことです。 JavaScript。

たとえば、リソースを作成するために、IMOがHTML5フォームで次のヘッダーを使用してPOSTすることはできません。

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

これは、HTML5enctype属性が列挙型であるため、通常以外のものapplication/x-www-formurlencodedmultipart/form-dataありtext/plain、無効であるためです。

...また、HTML4のすべてのブラウザーでサポートされているかどうかもわかりません(これは、より緩いencytpe属性を持っていますが、MIMEタイプが転送されたかどうかに関するブラウザー実装の問題になります)

このため、バージョン管理の最も適切な方法はURIを使用することだと思いますが、これは「正しい」方法ではないことを認めます。

于 2011-10-13T10:51:30.647 に答える
21

バージョンを URI に入れます。API のあるバージョンが別のバージョンの型を常にサポートするとは限らないため、リソースがあるバージョンから別のバージョンに移行されただけであるという議論は、まったく間違っています。XML から JSON にフォーマットを切り替えることとは異なります。型が存在しないか、意味的に変更されている可能性があります。

バージョンは、リソース アドレスの一部です。ある API から別の API にルーティングしています。ヘッダーでアドレス指定を隠すのは RESTful ではありません。

于 2012-06-05T15:09:52.800 に答える
13

REST API でバージョン管理を行うことができる場所がいくつかあります。

  1. 前述のように、URI で. これは、リダイレクトなどが適切に使用されている場合、扱いやすく、審美的にも快適です。

  2. Accepts: ヘッダーでは、バージョンはファイルタイプにあります。「mp3」対「mp4」のように。これも機能しますが、IMO よりも少しうまく機能しません...

  3. リソース自体。多くのファイル形式には、通常はヘッダーにバージョン番号が埋め込まれています。これにより、サポートされていない(新しい)バージョンが指定された場合に古いソフトウェアがパントできる一方で、ファイルタイプの既存のすべてのバージョンを理解することにより、新しいソフトウェアは「そのまま動作」することができます。REST API のコンテキストでは、URI を変更する必要はなく、渡された特定のバージョンのデータに対する応答のみを変更する必要があることを意味します。

3 つのアプローチすべてを使用する理由がわかります。

  1. 新しい API を「クリーン スイープ」するのが好きな場合、またはそのようなアプローチが必要なメジャー バージョンの変更の場合。
  2. クライアントが PUT/POST を実行する前に、それが機能するかどうかをクライアントに知らせたい場合。
  3. クライアントが PUT/POST を実行して、それが機能するかどうかを確認する必要がある場合でも問題ありません。
于 2011-10-24T16:39:53.580 に答える
8

REST API のバージョン管理は、他の API のバージョン管理に似ています。マイナーな変更はその場で行うことができますが、メジャーな変更にはまったく新しい API が必要になる場合があります。最も簡単な方法は、毎回ゼロから始めることです。これは、URL にバージョンを入れることが最も理にかなっている場合です。クライアントの生活を楽にしたい場合は、下位互換性を維持しようとします。これは、非推奨 (永続的なリダイレクト)、複数のバージョンのリソースなどで行うことができます。これはより手間がかかり、より多くの労力を必要とします。しかし、これは REST が "クールな URI は変更されない" で奨励していることでもあります。

最終的には、他の API 設計と同じです。クライアントの利便性と労力を比較検討してください。API にセマンティック バージョニングを採用することを検討してください。これにより、新しいバージョンの後方互換性がクライアントに明確になります。

于 2014-03-06T07:16:52.813 に答える