HATEOASを使用してRESTfulWebサービスを設計する場合、リンクを完全なURL( " http:// server:port / application / customers / 1234 ")として表示することと、パスだけ( "/ application /顧客/ 1234 ")?
HATEOASを使用してRESTfulWebサービスを設計する場合、リンクを完全なURL( " http:// server:port / application / customers / 1234 ")として表示することと、パスだけ( "/ application /顧客/ 1234 ")?
回答:
人々が「相対URI」と言うとき、微妙な概念のあいまいさがあります。
RFC3986の定義、一般的なURIが含まれています。
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
トリッキーなことは、スキームと権限が省略されている場合、「パス」部分自体が絶対パス(で始まる/
)または「ルートレス」相対パスのいずれかになり得ることです。例:
"http://example.com:8042/over/there?name=ferret"
/over/there
here
or./here
または../here
orなどがあります。したがって、質問が「サーバーが安らかな応答で相対パスを生成する必要があるかどうか」である場合、答えは「いいえ」であり、詳細な理由はここにあります。「相対URI」に反対するほとんどの人(私を含む)は、実際には「相対パス」に反対していると思います。
そして実際には、ほとんどのサーバー側MVCフレームワークは、などの絶対パスを使用して相対URIを簡単に生成できます。/absolute/path/to/the/controller
問題は、「サーバー実装でscheme://hostname:port
絶対パスの前にaをプレフィックスとして付ける必要があるかどうか」になります。OPの質問のように。これについてはよくわかりません。
一方では、完全なURIを返すサーバーが推奨されると思います。ただし、サーバーはこのようなソースコード内のhostname:port
ものをハードコーディングしないでください(そうでない場合は、絶対パスを使用して相対URIにフォールバックしたいと思います)。解決策は、サーバー側が常にHTTPリクエストの「ホスト」ヘッダーからそのプレフィックスを取得することです。ただし、これがすべての状況で機能するかどうかはわかりません。
一方、クライアントhttp://example.com:8042
が絶対パスと絶対パスを連結することはそれほど面倒ではないようです。結局のところ、クライアントはサーバーにリクエストを送信するときに、そのスキームとドメイン名をすでに知っていますか?
全体として、絶対URIを使用することをお勧めします。おそらく、絶対パスを使用して相対URIにフォールバックし、相対パスは使用しないでください。
誰がクライアントコードを書いているかによります。クライアントとサーバーを作成している場合は、それほど大きな違いはありません。クライアントまたはサーバーでURLを作成するのに苦労するでしょう。
ただし、サーバーを構築していて、他の人がクライアントコードを書くことを期待している場合は、完全なURIを提供すれば、他の人があなたをもっと愛してくれるでしょう。相対URIの解決には少し注意が必要です。まず、それらをどのように解決するかは、返されるメディアタイプによって異なります。Htmlにはbaseタグがあり、Xmlにはネストされたすべての要素にxml:baseタグを含めることができ、Atomフィードにはフィードにbaseを、コンテンツに異なるbaseを含めることができます。クライアントにベースURIに関する明示的な情報を提供しない場合、クライアントはリクエストURIから、またはおそらくContent-LocationヘッダーからベースURIを取得する必要があります。そして、その末尾のスラッシュに注意してください。ベースURIは、最後のスラッシュの右側にあるすべての文字を無視することによって決定されます。これは、相対URIを解決するときに、末尾のスラッシュが非常に重要になることを意味します。
少し言及する必要がある他の唯一の問題は、ドキュメントのサイズです。各アイテムに複数のリンクがある可能性のあるアイテムの大きなリストを返す場合、エンティティを圧縮しないと、絶対URLを使用するとエンティティにかなりの量のバイトが追加される可能性があります。これはパフォーマンスの問題であり、ケースバイケースで重要かどうかを判断する必要があります。
アプリケーションの拡張に応じて、負荷分散やフェイルオーバーなどを実行することをお勧めします。絶対URIを返す場合、クライアント側アプリは進化するサーバー構成に従います。
/xxx/yyy...
)として定義し、完全修飾URI(例http://api.example.com/xxx/yyy...
)を意味するものとして定義しない場合。
RayLouのトリコトミーを使用して、私の組織は(2)を支持することを選択しました。主な理由は、XSS(クロスサイトスクリプティング)攻撃を回避することです。問題は、攻撃者がサーバーから返される応答に独自のURLルートを挿入できる場合、後続のユーザー要求(ユーザー名とパスワードを使用した認証要求など)が攻撃者自身のサーバーに転送される可能性があることです*。
負荷分散のためにリクエストを他のサーバーにリダイレクトできるという問題を提起する人もいますが、(それは私の専門分野ではありませんが)クライアントを別のサーバーに明示的にリダイレクトすることなく負荷分散を有効にするより良い方法があると思いますホスト。
*この推論の行に欠陥がある場合はお知らせください。もちろん、目標はすべての攻撃を防ぐことではなく、少なくとも1つの攻撃手段を防ぐことです。
常に完全なURLを使用する必要があります。URLはすべて一意である必要があるため、リソースの一意の識別子として機能します。
私はまた、あなたが一貫しているべきだと主張します。Location HTTPヘッダーはHTTP仕様に基づいて完全なURLを想定しているため、新しいリソースが作成されると、完全なURLがLocationヘッダーでクライアントに返送されます。Locationヘッダーに完全なURLを指定してから、応答本文内のリンクに相対URIを指定するのはおかしいでしょう。
Location
ヘッダーの例が示すものです。URIスキームやサーバーのネットワークの場所を含まない絶対URIです。リンクとIDはしばしば混同されますが、同じものではありません。前者にはコンテキストがあり、後者にはコンテキストがありません。
絶対URIを使用することの1つの欠点は、APIをプロキシできないことです。
それを取り戻してください...真実ではありません。ドメインを含む完全なURLを取得する必要があります。
長所に関しては、クライアントが(絶対)パスに必要とする追加の処理を犠牲にして、送信されるバイト数が減少すると思います。gzipとしてのコンテンツエンコーディング、キャッシュヘッダーの適切な使用、クライアントでのetagの使用、条件付きリクエストを試した後でも、すべてのバイトを保存したい場合は、これが最終的に必要になる可能性がありますが、あなたの努力は他にありました。
短所については、将来的にリソース間でクライアントのフローをどのように方向付けることができるか(負荷分散、A / Bテストなど)に関する制御が失われると思います。Webの管理に関しては悪い習慣だと思います。 API。指定したURLは、クライアントにとって基本的に不透明ではなくなりました(URIの不透明性に関するWebアーキテクチャのTim Berners-Lee Axiomsを参照)。最終的には、URLスペースの構造のみに関係している場合でも、APIのクリエイティブな使用に関してクライアントを満足させる責任があります。明示的に定義されたURL変更を許可する必要がある場合は、ハイパーテキストアプリケーション言語で使用されているURIテンプレートの使用を検討してください。