REST APIクライアントとしてのWebアプリケーション:リソース識別子を処理する方法


21

RESTを実装しようとすると、RESTに関連するいくつかの概念が頭の中で競合します。

ビジネスロジックを保持するRESTフルバックエンドAPIシステムと、UIを提供するWebアプリケーションがあります。RESTに関するさまざまなリソース(特に、REST in Practice:Hypermedia and Systems Architecture)から、エンティティの生の識別子を公開せず、でハイパーリンクを返す必要があることを知っていrel="self"ます。

例を考えてみましょう。REST APIには、人を返すリソースがあります。

<Person>
  <Links>
    <Link rel="self" href="http://my.rest.api/api/person/1234"/>
  </Links>
  <Pets>
    <Link rel="pet" href="http://my.rest.api/api/pet/678"/>
  </Pets>
</Person>

問題はWebアプリケーションで発生します。ブラウザへのハイパーリンクを含むページを返すと仮定しましょう:

<body class="person">
  <p>
    <a href="http://my.web.app/pet/???????" />
  </p>
</body>

href属性に何を入れるべきですか?ユーザーがターゲットページを開いたときにエンティティを取得できるように、WebアプリケーションにAPIエンティティURLを保持するにはどうすればよいですか?

要件は矛盾しているようです:

  1. ハイパーリンクhrefは、UIをホストするシステムであるため、Webアプリケーションにつながるはずです
  2. hrefウェブアプリが対象ページが開いたときに、エンティティに対処することができなければならないので、エンティティのいくつかのIDを持っている必要があります
  3. WebアプリはRESTに対応していないため、REST URLを解析/構築しないでください。

URIは消費者に対して不透明でなければなりません。URIの発行者だけが、それを解釈してリソースにマップする方法を知っています。

その1234ため、RESTfulクライアントとしてのように扱う必要があるため、API応答URLから取得することはできませんhttp://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j。一方、WebアプリにつながるURLを指定する必要があり、アプリが何らかの方法でAPIの元のURLを復元し、そのURLを使用してAPIリソースにアクセスするには十分です。

最も簡単な方法は、おそらくリソースのAPI URLを文字列識別子として使用することです。しかし、そのようなWebページのURL http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234は見苦しいです。

デスクトップアプリや単一ページのjavascriptアプリにとっては、すべて簡単に思えます。彼らは継続的に生きているので、アプリケーションの存続期間中、サービスオブジェクトとともにURLをメモリに保持し、必要なときにそれらを使用することができます。

Webアプリでは、いくつかのアプローチを想像できますが、すべてが奇妙に見えます:

  1. API URLのホストを置き換えて、結果のみを保持します。大きな欠点は、APIが生成するURLを処理するためにWebアプリケーションが必要になることです。つまり、巨大な結合を意味します。さらに、私のWebアプリがURLの解釈を開始するため、再びRESTfulではありません。
  2. REST APIで生のIDをリンクとともに公開し、それらを使用してWebアプリのURLを作成し、WebアプリサーバーでIDを使用してAPIで必要なリソースを見つけます。これは優れていますが、Webアプリはブラウザーからの要求を処理するために何らかのフォームのget-by-id要求のチェーンを発行するRESTサービスナビゲーションを通過する必要があるため、Webアプリサーバーのパフォーマンスに影響します。ある程度ネストされたリソースの場合、これにはコストがかかる場合があります。
  3. selfAPIから返されたすべてのURLをWebアプリサーバーの永続的な(DB?)マッピングに保存します。それらのIDを生成し、IDを使用してWebアプリページのURLを構築し、RESTサービスリソースのURLを取得します。つまり、http://my.rest.api/pet/678URLを新しいキー(たとえば3)で保持し、WebページのURLをとして生成しますhttp://my.web.app/pet/3。これは、ある種のHTTPキャッシュ実装のように見えます。理由はわかりませんが、奇妙に思えます。

または、それはすべて、RESTful APIがWebアプリケーションのバックエンドとして機能できないことを意味しますか?


1
あなたが何を達成しようとしているのかは明確ではありません。おそらくあなたの単純な意図は、あなたが互いに重ねているアーキテクチャの層の下に隠されているからです。私があなたの問題について理解していることから、オプション2はシンプルで実行可能なソリューションです。ここでの「問題」は「RESTful API」に固有のものです。RestIsJustSqlReinventedを使用すると、RDBMSから十分に複雑なサブグラフを取得しようとすると、実際に同じ問題が発生します。クエリに最適化されたキャッシュまたは表現を使用します。
back2dos

回答:


5

質問の更新に対処するために編集され、以前の回答は削除されました

あなたの質問に対するあなたの変化を見て、私はあなたがもう少し直面している問題を理解していると思います。リソースの識別子であるフィールド(リンクのみ)がないため、GUI内の特定のリソースを参照する方法はありません(つまり、特定のペットを説明するページへのリンク)。

判断する最初のことは、ペットが飼い主なしで理にかなっているかどうかです。飼い主なしでペットを飼うことができる場合、ペットを参照するために使用できるペットのユニークなプロパティが必要です。実際のリソースIDはRESTクライアントが解析しないリンクに隠れているため、これがIDを直接公開しないことに違反するとは思わない。それを念頭に置いて、ペットリソースは次のようになります。

<Entity type="Pet">
    <Link rel="self" href="http://example.com/pets/1" />
    <Link rel="owner" href="http://example.com/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

アプリケーション全体で実際にリソースIDを変更することなく、そのペットの名前をSpotからFidoに更新できるようになりました。同様に、GUIで次のようなペットを参照できます。

http://example.com/GUI/pets/Spot

ペットが所有者なしでは意味をなさない場合(またはペットが所有者なしでシステムで許可されていない場合)、システム内のペットの「アイデンティティ」の一部として所有者を使用できます。

http://example.com/GUI/owners/John/pets/1(John のリストの最初のペット)

1つの小さな注意点として、ペットとピープルの両方が互いに別々に存在できる場合、APIのエントリポイントを「ピープル」リソースにしません。代わりに、PeopleとPetsへのリンクを含む、より一般的なリソースを作成します。次のようなリソースを返します。

<Entity type="ResourceList">
    <Link rel="people" href="http://example.com/api/people" />
    <Link rel="pets" href="http://example.com/api/pets" />
</Entity>

したがって、APIへの最初のエントリポイントのみを知っており、URLを処理せずにシステム識別子を把握することで、次のようなことができます。

ユーザーがアプリケーションにログインします。RESTクライアントは、次のような利用可能なリソースのリスト全体にアクセスします。

<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/1" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/1" />
        <Link rel="pet" href="http://example.com/api/pets/2" />
    </Pets>
    <UniqueName>John</UniqueName>
</Entity>
<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/2" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/3" />
    </Pets>
    <UniqueName>Jane</UniqueName>
</Entity>

GUIは各リソースをループし、UniqueNameを「id」として使用して各人のリストアイテムを出力します。

<a href="http://example.com/gui/people/1">John</a>
<a href="http://example.com/gui/people/2">Jane</a>

これを実行している間、「pet」というrelで見つかった各リンクを処理し、次のようなペットリソースを取得することもできます。

<Entity type="Pet">
    <Link rel="self" href="http://example.com/api/pets/1" />
    <Link rel="owner" href="http://example.com/api/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

これを使用すると、次のようなリンクを印刷できます。

<!-- Assumes that a pet can exist without an owner -->
<a href="http://example.com/gui/pets/Spot">Spot</a>

または

<!-- Assumes that a pet MUST have an owner -->
<a href="http://example.com/gui/people/John/pets/Spot">Spot</a>

最初のリンクに進み、エントリリソースに「ペット」という関係を持つリンクがあると仮定すると、GUIで制御フローは次のようになります。

  1. ページが開き、ペットスポットが要求されます。
  2. APIエントリポイントからリソースのリストをロードします。
  3. 「ペット」という用語に関連するリソースをロードします。
  4. 「pets」レスポンスから各リソースを調べ、スポットに一致するリソースを見つけます。
  5. スポットの情報を表示します。

2番目のリンクを使用すると、PeopleがAPIへのエントリポイントであり、最初にシステム内のすべての人のリストを取得し、一致する人を見つけ、次に所属するすべてのペットを見つけることを除いて、同様のイベントチェーンになりますその人に(再度relタグを使用して)Spotという名前の人を見つけて、それに関連する特定の情報を表示できるようにします。


ありがとう、マイク。質問を少し明確にするために更新しました。あなたの答えの問題は、RESTクライアントがURLを解析できることに同意できないことです。存在する場合、URLに結合されます。そして、これはRESTのコアアイデアの1つに違反します。クライアントはrelsを使用してリンクを選択する必要がありますが、URLの構造に関する知識を前提としないでください。RESTは、APIがrel同じままであれば、自由にURLを変更できると断言します。URLを解析すると、RESTよりもSOAPに近づきます。
パベルガティロフ

ありがとうございました。これまでに行ったアプローチについて説明してきました。ある意味では、識別子を公開します。唯一のことは、可能な限り自然な識別子を公開しようとすることです。
パベルガティロフ

6

すべては、RESTful APIがWebアプリケーションのバックエンドとして機能できないことを意味しますか?

REST APIとWebアプリケーションを区別する価値があるかどうかに挑戦します。あなたの「Webアプリケーションは、」ちょうど同じリソースの代替(HTML)表現でなければなりません-どのようにか、なぜあなたがアクセスを期待して、私は理解していないと言うことですhttp://my.rest.api/...http://my.web.app/...、彼らは同時に同じと異なることが。

この場合の「クライアント」はブラウザーであり、HTMLとJavaScriptを理解します。それ私の意見ではWebアプリケーションです。foo.comを使用して上記のWebアプリケーションにアクセスし、api.foo.comを介して他のすべてを公開することに同意しない場合があります。foo.comの「バックエンド」は、api.foo.comからリソースを発見する方法を完全に理解できます。あなたのウェブアプリケーションは単にプロキシになりました-あなたが一緒に(他の誰かから)別のAPIと話していた場合と同じです。

したがって、あなたの質問は、「他のシステムに存在する自分のURIを使用してリソースをどのように記述できますか?」に一般化できます。これを行う方法を理解する必要があるのはクライアント(HTML / JavaScript)ではなく、サーバーであると考える場合は簡単です。私の最初の課題に同意する場合、Webアプリケーションを別のREST APIにプロキシまたは委任する独立したREST APIと考えることができます。

クライアントがアクセスするmy.web.app/pets/1と、サーバー側のテンプレートから返されたもの、または他の表現(JSONやXMLなど)の非同期要求であるため、ペットインターフェイスを提示することがわかります。コンテンツタイプヘッダーは、 。

これを提供するサーバーは、ペットとは何か、リモートシステムでペットを発見する方法を理解する役割を果たします。これを行う方法はあなた次第です-単純にIDを取得して、不適切だと感じる別のURIを生成するか、リモートURIを保存してリクエストをプロキシする独自のデータベースを作成できます。このURIを保存するのは問題ありません-これはブックマークと同等です。個別のドメイン名を持つためだけに、これをすべて行うことになります。なぜこれが必要なのか、正直にはわかりません。RESTAPI URIもブックマーク可能でなければなりません。

あなたはすでにあなたの質問でこれのほとんどを取り上げましたが、あなたがやりたいことを実際に行う方法であると実際には認めていない方法で組み立てたと感じています(私が感じていることに基づいて任意の制約-APIとアプリケーションが別々であること。REST APIがWebアプリケーションのバックエンドになれないかどうかを尋ね、パフォーマンスが問題になることを示唆することで、あなたはすべて間違ったことに集中していると思います。マッシュアップを作成できないと言っているようなものです。ウェブが機能しないと言っているようなものです。


WebアプリがAPIの単なる表現になるとは思わない。1つのページにいくつかの子リソースといくつかのルートリソースを表示するなど、多くの違いがあります。2つのシステムが同じであると期待していると言って、WebアプリのURLにapiデータストレージの内部IDを含めないようにします。ここではパフォーマンスに関心はありませんが、問題ではありません。質問は、実際には「my.web.app/pets/3REST APIのURLを解析せずに3をどのように入れるか」です。
パベルガティロフ

自分の言い直しを修正する:「my.web.app/pets/3対応するREST APIリソースのURLを解析せずに3を入れるにはどうすればよいmy.rest.api/v0/persons/2/pets/3ですか?それともそこに何を入れますか?」
パベルガティロフ

クライアントの状態を、その状態を決定する表現と混同していると思います。不透明なので3、あなたは入れません。それはあなたのウェブアプリが望むどんなリソースも指し示します。それが他のいくつかのリソースの合成ビューである場合(他のシステム-APIはそれらの1つです)、Webアプリケーションサーバー内にそれらのシステムへのハイパーリンクを保存し、それらを取得し、それらの表現に解決します( JSONやXMLなど)を使用して、応答の一部として提供します。app/pets/3app/pets/3
ダグ

このように考えてください-APIとアプリを忘れてください。人々がお気に入りのFacebookやTwitterの投稿を収集できるサイトを作成したいとします。これらはリモートシステムです。独自の方法でこれらのシステムにURIをトンネリングまたはテンプレートしようとするつもりはありません。あなたは「ボード」リソースを作成したい、それがいることを知っているあなたのサーバーになりますboard/1へのポイントfacebook.com/post/123とはtwitter.com/status/789-あなたのボードの表現を提供するために行くとき、あなたはあなたと働くことができる表現にそれらのURIを解決しなければなりません。必要な場所にキャッシュします。
ダグ

APIをアプリとは大幅に異なるものにしたいので(これは依然として疑わしいと思います)、リモートシステムのように扱うことはそれと同じです。パフォーマンスは問題ではないとおっしゃいましたが、質問の中で、このような何かが「パフォーマンスに影響を与える」と言っていました。
ダグ

5

序文

この回答は、バックエンドREST APIが明示的に識別子を公開しないリソースの一意のブックマーク可能なURLを含む独自のURLスキームを、APIによって提供されるURLを解釈せずに管理する方法の質問に特に対処します。


発見可能性にはある程度の知識が必要なので、実世界のシナリオについての私の見解を以下に示します。

http://my.web.app/person結果に各人の詳細ページへのリンクが含まれる検索ページが必要だとします。フロントエンドコードが何かを行うために知っておくべきことの1つは、RESTデータソースのベースURLですhttp://my.rest.api/api。このURLへのGETリクエストに対する応答は次のとおりです。

<Links>
    <Link ref="self" href="http://my.rest.api/api" />
    <Link rel="person" href="http://my.rest.api/api/person" />
    <Link rel="pet" href="http://my.rest.api/api/pet" />
</Links>

私たちの目的は人々のリストを表示することなので、次にGETpersonリンクhref からhrefにリクエストを送信します。

<Links>
    <Link ref="self" href="http://my.rest.api/api/person" />
    <Link rel="search" href="http://my.rest.api/api/person/search" />
</Links>

検索結果を表示したいのでGETsearchリンクhrefにリクエストを送信して検索サービスを使用します。

<Persons>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/1"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/10"/>
        </Pets>
    </Person>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/2"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/20"/>
        </Pets>
    </Person>
</Persons>

最終的に結果が得られましたが、フロントエンドURLをどのように構築しますか?

確かにわかっている部分:APIベースURLを取り除き、残りをフロントエンド識別子として使用しましょう:

  • 既知のAPIベース: http://my.rest.api/api
  • 個々のエンティティに指定されたURL: http://my.rest.api/api/person/1
  • 一意のID: /person/1
  • ベースURL: http://my.web.app
  • 生成されたフロントエンドURL: http://my.web.app/person/1

結果は次のようになります。

<ul>
    <li><a href="http://my.web.app/person/1">A person</a></li>
    <li><a href="http://my.web.app/person/2">A person</a></li>
</ul>

ユーザーが詳細ページへのフロントエンドリンクをたどると、どのURL GETにその特定の詳細のリクエストを送信しpersonますか?バックエンドURLをフロントエンドURLにマッピングする方法を知っているので、単に逆にします。

  • フロントエンドURL: http://my.web.app/person/1
  • ベースURL: http://my.web.app
  • 一意のID: /person/1
  • 既知のAPIベース: http://my.rest.api/api
  • 生成されたAPI URL: http://my.rest.api/api/person/1

personURLが現在にhttp://my.rest.api/api/different-person-base/person/1なり、誰かが以前にブックマークしたようにREST APIが変更された場合、REST API http://my.web.app/person/1は(少なくともしばらく)古いURLに新しいURLへのリダイレクトで応答することにより、後方互換性を提供する必要があります。生成されるすべてのフロントエンドリンクには、新しい構造が自動的に含まれます。

お気づきかもしれませんが、APIをナビゲートするために知っておくべきことがいくつかあります。

  • APIベースURL
  • person関係
  • search関係

これに何か問題があるとは思わない。特定のURL構造を想定しているわけではないため、エンティティURLの構造はhttp://my.rest.api/api/person/1変更される可能性があります。APIが下位互換性を提供している限り、コードは引き続き機能します。


ルーティングロジックが2つのフロントエンドURLの違いをどのように判断できるかを尋ねました。

  • http://my.rest.api/api/person/1
  • http://my.rest.api/api/pet/3

最初に、この例でUIとREST APIに別々のベースURLを使用しているときに、コメントでAPIベースを使用したことを指摘します。個別のベースを使用して例を続けますが、ベースの共有は問題ではありません。リクエストのAcceptヘッダーのメディアタイプを使用して、UIルーティングメソッドをマップできます(またはできるはずです)。

特定の詳細ページへのルーティングに関してはself、APIによって提供されるURL の構造(つまり、不透明な文字列ID)に関する知識を避けることに厳格な場合、2つのURLを区別できません。これを機能させるために、既知の別の情報-作業しているエンティティタイプ-をフロントエンドURLに含めましょう。

以前は、フロントエンドURLは次の形式でした。 ${UI base}/${opaque string id}

新しい形式は次のとおりです。 ${UI base}/${entity type}/${opaque string id}

したがって、/person/1例を使用すると、結果はになりhttp://my.web.app/person/person/1ます。

この形式では、UIルーティングロジックがで動作し/person/person/1、文字列の最初のトークンが自分で挿入されたことを知っているため、それを引き出して、それに基づいて適切な(この例では人)詳細ページにルーティングできます。そのURLについて気味が悪いと感じる場合は、そこにもう少し挿入できます。多分: http://my.web.app/person/detail/person/1

その場合/person/detail、ルーティングのためにを解析し、残りを不透明な文字列IDとして使用します。


これにより、WebアプリとAPIが非常に緊密に結合されると思います。

生成されたフロントエンドURLにはAPI URLの一部が含まれているため、古い構造をサポートせずにAPI URL構造が変更された場合、ブックマークされたURLをに変換するためにコードを変更する必要がありますAPI URLの新しいバージョン。つまり、REST APIがリソースのID(不透明な文字列)を変更した場合、古いIDを使用してそのリソースについてサーバーと通信することはできません。そのような状況でコードの変更を避けることはできないと思います。

WebアプリのURL構造をAPIのURL構造と異なるものにしたい場合はどうすればよいですか?

任意のURL構造を使用できます。一日の終わりには、特定のリソースのブックマーク可能なURLに、そのリソースを一意に識別するAPI URLを取得するために使用できるものを含める必要があります。独自の識別子を生成し、アプローチ#3のようにAPI URLでキャッシュすると、そのエントリがキャッシュからクリアされた後、誰かがそのブックマークされたURLを使用しようとするまで機能します。

WebアプリのエンティティがAPIエンティティ1-1にマッピングされなかった場合はどうなりますか?

答えは関係によって異なります。いずれにしても、フロントエンドをAPI URLにマップする方法が必要です。


このアプローチには1つの問題があります。それは実際に私のソリューションのリストで一番です。私が取得できないのはこれです:WebアプリがURLを解釈せず、一意のIDを不透明な文字列(ちょうどperson/1pet/3)として扱う場合、ブラウザが開いたらhttp://my.rest.api/api/person/1人のUIが表示されることをどのように知っていますか?開きhttp://my.rest.api/api/pet/3、ペットUI?
パベルガティロフ

良い質問!回答を更新しました。
マイクパートリッジ

ありがとう、マイク。これにより、WebアプリとAPIが非常に緊密に結合されると思います。WebアプリのURL構造をAPIのURL構造と異なるものにしたい場合はどうすればよいですか?WebアプリのエンティティがAPIエンティティ1-1にマッピングされなかった場合はどうなりますか?私はまだ、いくつかの識別子を公開するアプローチを取る方が良いと思いますが、ナビゲーションにリンクを使用するようクライアントに促します。
パベルガティロフ

これは興味深いトピックなので、私は何も見逃さないことを望みます。あなたのコメントに対する回答で回答を更新しました。一部の識別子を公開することは、完全なRESTful性と使いやすさの間の良い妥協点だと思います。
マイクパートリッジ

ここでの私の主な関心事はもう少し実用的です。ASP.NET MVCを使用してWebアプリを実装しますが、いくつかの内部ルールにより、アプリがサポートするURLパターンを定義する必要があります。つまり、/ a / {id}が定義されている場合、アプリは/ a / 1を処理しますが、/ a / 1 / b / 2は処理しません。これにより、REST APIのURLがブックマークされたURLを保持するだけでなく、ルートからナビゲートされたときにWebアプリが機能するように変更された場合、Webアプリを再コンパイルする必要が生じます。HTMLページに埋め込まれたハイパーリンクは、それなしでは機能しないからです。
パベルガティロフ

2

それに直面しましょう、魔法の解決策はありません。リチャードソン成熟度モデルを読みましたか?RESTアーキテクチャの成熟度を、リソース、HTTP動詞、ハイパーメディアコントロールの3つのレベルに分けます。

エンティティの生の識別子を公開するのではなく、rel = "self"でハイパーリンクを返します

これはハイパーメディアコントロールです。本当に必要ですか?このアプローチには、いくつかの非常に良い利点があります(それらについては、こちらで読むことができます)。しかし、無料の食事のようなものはなく、それらを手に入れたいなら、あなたは一生懸命働かなければなりません(例えば、あなたの2番目の解決策)。

それはバランスの問題です-パフォーマンスを犠牲にして(そしてコードをより複雑にしますが)より柔軟なシステムを得たいですか?または、物事をより速く簡単に保ちながら、API /モデルに変更を加えたときに後で支払いたいですか?

同様のシステム(ビジネスロジック層、Web層、およびWebクライアント)を開発した人として、2番目のオプションを選択しました。私のグループはすべての層を開発したので、(Web層にエンティティIDを知らせ、APIのURLを構築することにより)少しカップリングして、より簡単なコードを取得する方が良いと判断しました。下位互換性もこのケースでは関係ありませんでした。

Webアプリケーションがサードパーティによって開発された場合、または下位互換性が問題であった場合、Webアプリケーションを変更せずにurl構造を変更できるという大きな価値があったため、異なる方法を選択した可能性があります。コードの複雑化を正当化するのに十分です。

すべては、RESTful APIがWebアプリケーションのバックエンドとして機能できないことを意味しますか?

完璧なREST実装を作成する必要がないことを意味すると思います。2番目のソリューションを使用するか、エンティティIDを公開するか、api urlを渡すことができます。その意味とトレードオフを理解していれば問題ありません。


0

Atom Syndication Formatあなたがあなたに似ている何かに固執するなら私は良いことです。

ここでは、追加の要素/属性を使用して、表現されるエントリを記述するメタデータを指定できます。

  • [RFC4287] に従って、エントリを一意に識別するURIが含まれています

  • どおり[RFC4287] 、この要素はオプションです。含まれる場合、クライアントがエントリを取得するために使用するURIが含まれます。

これはちょうど私の2セントです。


私は何かを得られないかもしれませんが、あなたの答えはREST APIのクライアントであるWebアプリのURLを生成する方法を説明していないように思えますか?
パベルガティロフ

0

URLについては心配せず、メディアタイプについても心配しないでください。

こちらをご覧ください(特に3番目の箇条書き)。

REST APIは、リソースの表現とアプリケーションの状態の駆動に使用されるメディアタイプの定義、または既存の標準メディアタイプの拡張リレーション名やハイパーテキスト対応マークアップの定義に、記述的な努力のほとんどすべてを費やすべきです。 。


典型的なWebアプリの場合、クライアントは人間です。ブラウザは単なるエージェントです。

のようなアンカータグ

          <a href="example.com/foo/123">click here</a>

のようなものに対応

          <link type="text/html" rel="self" href="example.com/foo/123">

ユーザーにとってURLは依然として不透明であり、ユーザーが気にするのはメディアタイプ(例text/html, application/pdf, application/flv, video/x-flv, image/jpeg, image/funny-cat-picture etc)だけです。アンカー(およびtitle属性)に含まれる説明テキストは、人間が理解できる方法で関係タイプを拡張する方法にすぎません。

URIをクライアントに対して不透明にしたいのは、カップリング(RESTの主要な目標の1つ)を減らすためです。サーバーは、クライアントに影響を与えることなくURIを変更/再編成できます(適切なキャッシングポリシーがあれば、キャッシングがまったくないことを意味します)。

要約すれば

クライアント(人間または機械)がURLではなくメディアの種類と関係を気にするようにしてください。そうすれば大丈夫です。


Rodrick、私の質問はAPIの構築に関するものではなく、RESTful APIの上に置かれるWebアプリケーションの構築に関するものです。メディアタイプがどのようにWebアプリのURLを構築するのに役立つかについてはほとんど理解できません。ただし、メディアの種類はサービス契約と発見可能性にとって重要です。
パベルガティロフ

@PavelGatilov-Webアプリのクライアントは人間ですか?
ロドリックチャップマン

はい、そうです。そして、非常に不十分なもの。
パベルガティロフ

0

最も簡単な方法は、おそらくリソースのAPI URLを文字列識別子として使用することです。しかし、http: //my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234のようなWebページのURL は見苦しいです。

あなたが正しいと思う、それは最も簡単な方法です。URLを相対化して、http://my.rest.api/api見苦しくないようにすることができます。

http://my.web.app/person/person%2F1234

APIによって提供されるURLがそのベースに関連していない場合、Ifい形式になります。

http://my.web.app/person/http%3A%2F%2Fother.api.host%2Fapi%2Fperson%2F1234

さらに一歩進むには、APIサーバーからの応答を調べて、表示するビューの種類を決定し、パスセグメント区切り文字とコロンのエンコードを停止します。

http://my.web.app/person/1234 (best case)
http://my.web.app/http://other.api.host/api/person/1234 (ugly case)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.