REST URIをバージョン管理する方法


111

REST URIをバージョン管理する最良の方法は何ですか?現在、URI自体にバージョン#があります。

http://example.com/users/v4/1234/

この表現のバージョン4。

バージョンはqueryStringに属していますか?すなわち。

http://example.com/users/1234?version=4

または、バージョン管理は別の方法で行うのが最善ですか?


回答:


34

URI自体の一部(オプション1)にするのが最善だと思います。v4はv3とは異なるリソースを識別するためです。2番目のオプションのようなクエリパラメータは、リソースではなく、リクエストに関連する追加の(クエリ)情報を渡すのに最適です


11
問題は、それは私たちが議論している別のリソースですか?またはそのリソースの別の表現?RESTは表現とリソースを区別しますか?
Cheeso 2009年

1
@Cheeso-OPは、それが別のリソースではなく別の表現であることを示しているため、私の答えです。
グレッグブナ

これは前にここでは詳細に回答されているstackoverflow.com/q/389169/104261
タラスAlenin

「2番目のオプションのようなクエリパラメータの+1は、リソースではなく、リクエストに関連する追加(クエリ)情報を渡すのに最適です」
andy

別の表現では、「Accept」のようなヘッダーを使用する必要があると思います。その後、クライアントはサーバーに「バージョン4のみを受け入れる」と指定でき、サーバーはその表現で応答できます。承認が送信されない場合は、最後のバージョンが提供されます。
カルロスベルデス

190

URLをバージョン管理しないでください。

  • あなたはパーマリンクを壊す
  • URLの変更は、インターフェースを介して病気のように広がります。変更されていない表現を使用して、変更された表現をポイントしますか?URLを変更すると、古いクライアントが壊れます。URLをそのままにしておくと、新しいクライアントが機能しなくなる可能性があります。
  • メディアタイプのバージョン管理は、はるかに柔軟なソリューションです。

リソースがapplication / vnd.yourcompany.user + xmlのバリアントを返すと仮定すると、新しいapplication / vnd.yourcompany.userV2 + xmlメディアタイプのサポートを作成し、コンテンツネゴシエーションのマジックを通じてv1とv2クライアントは平和的に共存できます。

RESTfulインターフェースでは、コントラクトに最も近いものは、クライアントとサーバー間で交換されるメディアタイプの定義です。

クライアントがサーバーと対話するために使用するURLは、以前に取得した表現に埋め込まれたサーバーによって提供される必要があります。クライアントが認識する必要がある唯一のURLは、インターフェースのルートURLです。URLにバージョン番号を追加しても意味があるのは、クライアントでURLを作成する場合のみです。これは、RESTfulインターフェースで行うことを想定していません。

メディアタイプを変更して既存のクライアントを壊す必要がある場合は、新しいクライアントを作成して、URLをそのままにしてください。

そして、メディアタイプとしてapplication / xmlとapplication / jsonを使用している場合、これは意味をなさないと現在述べている読者のために。それらをバージョン管理するにはどうすればよいですか?あなたではない。これらのメディアタイプは、コードダウンロードを使用して解析しない限り、RESTfulインターフェースにはほとんど役に立ちません。その時点で、バージョン管理は重要なポイントです。


66
箇条書きに対処する。1.パーマリンクは特定のバージョンにリンクしているため、パーマリンクを解除しません。2.すべてのバージョンがバージョン管理されている場合、これは問題ではありません。古いURLは引き続き機能します。理想的には、バージョン4のURLがバージョン3のリソースへの関連付けを返すことを望まないでしょう。3.おそらく
マイクポーン

10
Webブラウザの新しいバージョンにアップグレードしたときに、ブックマークしたすべてのお気に入りが壊れたと想像してみてください。概念的には、ユーザーがリソースへのリンクを保存しているのではなく、リソースのバージョンのバージョンへのリンクを保存していることを思い出してください。
ダレルミラー

11
@Gili REST APIが自己記述的であるという要件を満たすためには、コンテンツタイプヘッダーがメッセージの完全な意味論的記述を提供する必要があります。つまり、メディアタイプはデータコントラクトです。application / xmlまたはapplication / jsonを配信する場合、そのXML / Jsonに何が含まれているかについてクライアントに何も伝えていません。クライアントアプリケーションが到達した瞬間に、メッセージにない情報に基づいてカップリングを作成している/ Customer / Nameを引き出します。RESTfulnessを実現するには、帯域外結合をなくすことが重要です。
Darrel Miller、

6
@Giliクライアントは、ルートURL以外のAPIのURLを事前に知っているべきではありません。表現形式を特定のURLに関連付けないでください。それはメディアの種類を選択することになると、あなたは本当にアプリケーション/ vnd.mycompany.myformat + xmlまたはなど、XHTML、アトム、RDF、のような標準化のような特定の形式の間で選択したする必要があります
ダレル・ミラー

4
APIバージョンを別のヘッダーフィールドにすることは意味がありますか?受け入れ:application / com.example.myapp + json; version = 1.0
Erik、

21

ああ、私は再び古い不機嫌そうな帽子をかぶっています。

ReSTの観点からは、それはまったく問題ではありません。ソーセージではありません。

クライアントは、追跡したいURIを受け取り、不透明な文字列として扱います。その中に何を入れても、クライアントはバージョン識別子などを認識しません

クライアントが知っているのは、メディアタイプを処理できることです。私は、Darrelのアドバイスに従うことをお勧めします。また、私は個人的に、安静なアーキテクチャで使用されているフォーマットを4回変更する必要があると、何か深刻な問題が発生していることを示す巨大で大きな警告の兆候をもたらし、変更の回復力のためにメディアタイプを設計する必要性を完全に回避できると感じています。

ただし、どちらの方法でも、クライアントは、理解できる形式のドキュメントのみを処理し、そのリンクをたどることができます。リンク関係(遷移)について知っている必要があります。したがって、URIの内容はまったく無関係です。

私は個人的にhttp:// localhost / 3f3405d5-5984-4683-bf26-aca186d21c04に投票します

URIの最初または最後にv4を配置する必要があるかどうかを質問するために、以降のクライアント開発者またはシステムに触れる人を防ぐ完全に有効な識別子(およびサーバーの観点から、4バージョン、ただし4つのメディアタイプ)。


表現を大幅に変更する必要があり、下位互換性がない場合はどうなりますか?
Mike Pone

1
名前空間と拡張可能なxsd、または既存のxml形式のike atomを使用するなど、拡張可能な方法でメディアタイプを設計することで、これを防ぐことができます。あなたが本当にしなければならないなら、別のメディアタイプが行く方法です。
SerialSeb、2009年

1
私はこの完全に有効な回答が好きですが、提案されたURIは、「ハッキング可能な」URIが必要な実際のシナリオよりも、要点を示すためのものだと思います。
Dave Van den Eynde 2012年

10

バージョンをURLに含めないでください。バージョンをリクエストのAcceptヘッダーに含めてください。このスレッドの私の投稿を参照してください。

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

URLにバージョンを貼り付け始めると、次のような愚かなURLになります:http : //company.com/api/v3.0/customer/123/v2.0/orders/4321/

そして、忍び寄る他の問題がたくさんあります-私のブログを参照してください:http : //thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html


11
申し訳ありませんが、このような愚かなURLになるとは思いません。バージョン番号を特定のリソースまたは(さらに悪い)特定の表現に結び付けています。それは愚かなことです、IMO。むしろ、APIのバージョン管理を行っているため、URIに複数のバージョンが含まれることはありません。
fool4jesus 2013年


3

APIのバージョン管理には4つの異なる方法があります。

  • URIパスにバージョンを追加:

    http://example.com/api/v1/foo
    
    http://example.com/api/v2/foo
    

    重大な変更がある場合は、次のようにバージョンをインクリメントする必要があります:v1、v2、v3 ...

    次のようなコードでコントローラを実装できます。

    @RestController
    public class FooVersioningController {
    
    @GetMapping("v1/foo")
    public FooV1 fooV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping("v2/foo")
    public FooV2 fooV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • リクエストパラメータのバージョン管理:

    http://example.com/api/v2/foo/param?version=1
    http://example.com/api/v2/foo/param?version=2
    

    APIの使用方法に応じて、バージョンパラメータはオプションまたは必須になります。

    実装は次のようになります。

    @GetMapping(value = "/foo/param", params = "version=1")
    public FooV1 paramV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/param", params = "version=2")
    public FooV2 paramV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • カスタムヘッダーを渡す:

    http://localhost:8080/foo/produces
    

    ヘッダー付き:

    headers[Accept=application/vnd.company.app-v1+json]
    

    または:

    headers[Accept=application/vnd.company.app-v2+json]
    

    このスキームの最大の利点は、主にセマンティクスです。バージョン管理に関係することでURIを乱雑にする必要はありません。

    可能な実装:

    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
    public FooV1 producesV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
    public FooV2 producesV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • ホスト名の変更またはAPIゲートウェイの使用:

    基本的に、APIをあるホスト名から別のホスト名に移動します。同じリソースに対して新しいAPIを構築するためにこれを呼び出すことさえできます。

    また、APIゲートウェイを使用してこれを行うこともできます。


2

RESTサービスが使用前に認証を必要とする場合、APIキー/トークンをAPIバージョンに簡単に関連付け、内部でルーティングを行うことができます。APIの新しいバージョンを使用するには、そのバージョンにリンクされた新しいAPIキーが必要になる場合があります。

残念ながら、このソリューションは認証ベースのAPIでのみ機能します。ただし、バージョンがURIに含まれないようにします。



1

URIの最後にオプションの値としてバージョンを含めます。これは、/ V4のようなサフィックスか、あなたが説明したようなクエリパラメータかもしれません。/ V4をクエリパラメータにリダイレクトして、両方のバリエーションをサポートすることもできます。


1

バージョン管理にURIを使用する場合は、バージョン番号をAPIルートのURIに含める必要があります。これにより、すべてのリソース識別子にバージョン番号を含めることができます。

技術的には、REST APIはURLの変更(統一されたインターフェース制約の結果)によって壊れることはありません。関連するセマンティクス(たとえば、API固有のRDF語彙)が下位互換性のない方法(まれ)で変更された場合にのみ機能します。現在、多くのpplは、ナビゲーション(HATEOAS制約)とボキャブのリンクを使用してREST応答(自己記述型メッセージ制約)に注釈を付けていないため、クライアントが壊れています。

関連するメタデータと表現の構造を短い文字列に入れても機能しないため、カスタムMIMEタイプとMIMEタイプのバージョン管理は役に立ちません。Ofc。メタデータと構造は頻繁に変更されるため、バージョン番号も...

したがって、質問に答えて、要求と応答にvocabs(Hydraリンクされたデータ)で注釈を付け、バージョニングを忘れるか、下位互換性のない語彙の変更によってのみ使用する(たとえば、語彙を別の語彙に置き換える場合)。


0

私はこれをMIMEタイプで行うことに賛成票を投じますが、URLでは投票しません。しかし、理由は他の人と同じではありません。

一意のリソースを見つけるために、URLは一意でなければならない(これらのリダイレクトを除く)。それで、もしあなた/v2.0がURLで受け入れるなら、なぜそれが/ver2.0or /v2/またはor ではないの/v2.0.0ですか?あるいは-alpha-beta?(それから完全にsemverのコンセプトになります

そのため、MIMEタイプのバージョンはURLよりも受け入れられます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.