WebサービスREST APIバージョン管理の既知のハウツーまたはベストプラクティスはありますか?
AWSがエンドポイントのURLによってバージョン管理を行うことに気づきました。これが唯一の方法ですか、それとも同じ目標を達成する他の方法はありますか?複数の方法がある場合、それぞれの方法のメリットは何ですか?
WebサービスREST APIバージョン管理の既知のハウツーまたはベストプラクティスはありますか?
AWSがエンドポイントのURLによってバージョン管理を行うことに気づきました。これが唯一の方法ですか、それとも同じ目標を達成する他の方法はありますか?複数の方法がある場合、それぞれの方法のメリットは何ですか?
回答:
これは良い質問です。URI設計のトピックは、同時にREST APIの最も顕著な部分であり、そのため、そのAPIのユーザーに対する長期的なコミットメントになる可能性があります。
アプリケーションの進化と、それほどではありませんが、そのAPIは現実の事実であり、プログラミング言語のように複雑に見える製品の進化にさえ似ているため、URI設計の自然な制約は少なく、保存する必要があります時間の経過とともに。アプリケーションとAPIの寿命が長いほど、アプリケーションとAPIのユーザーへの取り組みが大きくなります。
一方、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バージョンにバインドするのが簡単です。ただし、これは限られた時間、つまり開発中のみです。
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バージョンを使用するよう通知される必要があります。したがって、次のような古い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
このままである適切なバージョンのリソースURIにリダイレクトするHTTPヘッダーと共に使用されるリダイレクトを示す30x HTTPステータスコードのいずれかを返す必要がありますLocation
。
http:// shonzilla / api / customers / 1234
APIバージョン管理シナリオに適した少なくとも2つのリダイレクトHTTPステータスコードがあります。
301永続的に移動され、リクエストされたURIを持つリソースが別のURI(APIバージョン情報を含まないリソースインスタンスパーマリンクである必要があります)に永続的に移動されたことを示します。このステータスコードを使用して、廃止またはサポートされていないAPIバージョンを示し、バージョン付きリソースURIがリソースパーマリンクに置き換えられたことをAPIクライアントに通知できます。
302要求されたリソースが一時的に別の場所にあるが、要求されたURIはまだサポートされている可能性があることを示す発見。このステータスコードは、バージョンのないURIが一時的に利用できず、リダイレクトアドレスを使用してリクエストを繰り返す必要がある場合(APiバージョンが埋め込まれたURIを指すなど)、クライアントにそれを使用し続けるように伝えたい場合(つまり、パーマリンク)。
410 Gone
リダイレクトが新しい場所に互換性がない場合に互換性があることを示す可能性があるため、廃止され、サポートされなくなったAPIはを返す必要があると言います。APIが廃止されただけでまだ存在する場合はWarning
、応答のHTTPヘッダーがオプションである可能性があります。
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")。それはバージョンが行くべきところです。同じものが別のフォーマットで必要な場合があり、クライアントが必要なものを要求できるはずであるという事実は誰もが気にしないようです。上記の例では、クライアントが求めているため、ANYない、本当にそれが欲しいものの真の表現-リソースの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/
URLにバージョンを含めることは実用的で便利であることがわかりました。使用しているものを一目で簡単に確認できます。受け入れられた回答が示唆するように、使いやすさのために/ foo /(最新バージョン)のエイリアスとして/ fooを使用し、URLを短く/よりクリーンにします。
下位互換性を永続的に維持することは、多くの場合、コストがかかり、非常に困難です。非推奨、ここで提案されているようなリダイレクト、ドキュメント、およびその他のメカニズムについて事前に通知することをお勧めします。
リソース表現のバージョン管理はRESTのアプローチに従っていることに同意しますが、カスタムMIMEタイプ(またはバージョンパラメータを追加するMIMEタイプ)の大きな問題の1つは、HTMLのAcceptおよびContent-Typeヘッダーへの書き込みが不十分であることです。 JavaScript。
たとえば、リソースを作成するために、IMOがHTML5フォームで次のヘッダーを使用してPOSTすることはできません。
Accept: application/vnd.company.myapp-v3+json
Content-Type: application/vnd.company.myapp-v3+json
これは、HTML5 enctype
属性が列挙型であるため、通常以外のものapplication/x-www-formurlencoded
でmultipart/form-data
ありtext/plain
、無効であるためです。
...また、HTML4のすべてのブラウザでサポートされていることも確かです(これにはより緩やかなencytpe属性がありますが、MIMEタイプが転送されたかどうかに関するブラウザ実装の問題になります)
このため、バージョン管理の最も適切な方法はURI経由であると感じていますが、これは「正しい」方法ではないことを受け入れます。
REST APIでバージョニングを実行できる場所がいくつかあります。
前述のとおり、URI内。これは扱いやすく、リダイレクトなどが適切に使用されている場合、審美的にも快適です。
Accepts:ヘッダーで、バージョンはファイルタイプにあります。「mp3」と「mp4」のように。これも機能しますが、IMOは少しうまく機能しません...
リソース自体。多くのファイル形式には、通常はヘッダーにバージョン番号が埋め込まれています。これにより、サポートされていない(新しい)バージョンが指定されている場合、古いソフトウェアはパントすることができますが、新しいソフトウェアはファイルタイプのすべての既存のバージョンを理解することで「機能する」だけです。REST APIのコンテキストでは、URIを変更する必要はなく、渡されたデータの特定のバージョンへの応答だけが必要です。
3つのアプローチすべてを使用する理由がわかります。
REST APIのバージョン管理は、他のAPIのバージョン管理に似ています。小さな変更を行うことができます。大きな変更には、まったく新しいAPIが必要になる場合があります。あなたにとって最も簡単なのは、毎回ゼロから始めることです。これは、URLにバージョンを入れることが最も理にかなっている場合です。クライアントの生活をより簡単にしたい場合は、下位互換性を維持しようとします。これは、廃止(永続的なリダイレクト)、複数のバージョンのリソースなどで実行できます。これはより手間がかかり、より多くの努力が必要です。しかし、それはRESTが「クールなURIは変更しない」で推奨していることでもあります。
結局のところ、それは他のAPIデザインと同じです。努力をクライアントの利便性と比較検討します。APIにセマンティックバージョニングを採用することを検討してください。これにより、新しいバージョンの下位互換性がクライアントに明確になります。