web-dev-qa-db-ja.com

APIバージョン管理のベストプラクティス

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

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

878
Swaroop C H

これは良くて難しい質問です。 RIデザインは同時にREST AP​​Iの最も顕著な部分であり、であるため、潜在的にlong-そのAPIのユーザーに対する契約期間

アプリケーションの進化、そしてそれほどではないがそのAPIは現実であり、プログラミング言語のような一見複雑な製品の進化にさえ似ているため、RIデザイン自然な制約およびそれ時間をかけて保存する必要があります。アプリケーションとAPIの寿命が長いほど、アプリケーションとAPIのユーザーに対するコミットメントは大きくなります。

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

時間が経つにつれて、特定の各リソースに新しいリソースと新しい属性を追加する必要が生じる場合がありますが、特定のリソースにアクセスするためにAPIユーザーが従う方法は、リソースアドレッシングスキームがパブリックになり最終的に変更されないはずです。

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

さらに、APIバージョンをURIに埋め込むと、 アプリケーション状態のエンジンとしてのハイパーメディア (Roy T. Fieldings PhD論文で述べられている)の概念が混乱するため、リソースアドレス/ URIが切り替わりますAPIバージョンをリソースURIに長期間保持すべきではないと結論付けます-APIユーザーが依存できるリソースURIはパーマリンクである必要があることを意味します。

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

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

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

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

ただし、APIバージョンがURIで明確に表示されるため、注意が必要です。RI設計でAPI履歴が表示/親になるしたがって、時間の経過とともに変化する傾向があるため RESTのガイドラインに反します。同意する!

この合理的な異論を回避する方法は、バージョンレスAPIベースURIで最新のAPIバージョンを実装することです。この場合、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

さらに、oldAPIを引き続き参照しようとする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

リダイレクションを示す30x HTTPステータスコードのいずれかを返す必要があります。これはLocation HTTPヘッダーとともに使用され、適切なバージョンのリソースURIにリダイレクトされます。

http:// shonzilla/api/customers/1234

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

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

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

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

683
Shonzilla

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/
273
jeremyh

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

後方互換性を永遠に維持することは、多くの場合、法外なコストで非常に困難です。私たちは、非推奨の予告、ここで提案されているようなリダイレクト、ドキュメント、その他のメカニズムを提供することを好みます。

99
Yoav Shapira

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

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

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

これは、HTML5のenctype属性が列挙型であるためです。したがって、通常のapplication/x-www-formurlencodedmultipart/form-dataおよびtext/plain以外のものはすべて無効です。

...また、HTML4のすべてのブラウザでサポートされていると確信しています(より緩やかなencytpe属性がありますが、MIMEタイプが転送されたかどうかについてはブラウザの実装上の問題になります)。

このため、私は現在、URIを使用することが最も適切な方法であると感じていますが、それが「正しい」方法ではないことを認めます。

46
Kevsy

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

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

21
Sean O'Dell

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

  1. すでに述べたように、URIの中で。リダイレクトなどがよく使用されている場合、これは扱いやすく、美的にも魅力的です。

  2. Accepts:ヘッダー内にあるので、バージョンはファイルタイプになります。 'mp3'と 'mp4'のように。 IMOそれはそれより少し少しうまく動作しますが、これも動作します...

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

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

  1. 新しいAPIを「一掃する」場合や、そのような方法が必要な場合はメジャーバージョンの変更を行う場合があります。
  2. pUT/POSTを実行する前にクライアントにそれが機能するかどうかを知らせたい場合。
  3. うまくいくかどうかを調べるためにクライアントがPUT/POSTを実行しなければならない場合は問題ありません。
13
pjz

REST AP​​Iのバージョン管理は、他のAPIのバージョン管理と似ています。小さな変更はその場で行うことができます、大きな変更は全く新しいAPIを必要とするかもしれません。一番簡単なのは毎回最初から始めることです。それはURLにバージョンを入れるのが最も理にかなっているときです。クライアントの生活を楽にしたいのであれば、後方互換性を維持しようとします。これは、非推奨(永続的なリダイレクト)、複数のバージョンのリソースなどで実現できます。しかし、それはまたRESTが "クールなURIは変わらない"の中で奨励するものです。

結局、他のAPI設計とまったく同じです。顧客の都合に反して努力を量る。あなたのAPIにセマンティックバージョニングを採用することを検討してください。それはあなたのクライアントにとってあなたの新しいバージョンがどれほど後方互換性であるかを明らかにします。

8