HATEOAS:絶対URLまたは相対URL?


回答:


83

人々が「相対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

トリッキーなことは、スキームと権限が省略されている場合、「パス」部分自体が絶対パス(で始まる/)または「ルートレス」相対パスのいずれかになり得ることです。例:

  1. 絶対URIまたは完全なURI:"http://example.com:8042/over/there?name=ferret"
  2. そしてこれは相対URIであり、絶対パスがあります/over/there
  3. そして、これは相対URIであり、相対パスhereor./hereまたは../hereorなどがあります。

したがって、質問が「サーバーが安らかな応答で相対パスを生成する必要があるかどうか」である場合、答えは「いいえ」であり、詳細な理由はここにあります。「相対URI」に反対するほとんどの人(私を含む)は、実際には「相対パス」に反対していると思います。

そして実際には、ほとんどのサーバー側MVCフレームワークは、などの絶対パスを使用して相対URIを簡単に生成できます。/absolute/path/to/the/controller問題は、「サーバー実装でscheme://hostname:port絶対パスの前にaをプレフィックスとして付ける必要があるかどうか」になります。OPの質問のように。これについてはよくわかりません。

一方では、完全なURIを返すサーバーが推奨されると思います。ただし、サーバーはこのようなソースコード内hostname:portものをハードコーディングしないでください(そうでない場合は、絶対パスを使用して相対URIにフォールバックしたいと思います)。解決策は、サーバー側が常にHTTPリクエストの「ホスト」ヘッダーからそのプレフィックスを取得することです。ただし、これがすべての状況で機能するかどうかはわかりません。

一方、クライアントhttp://example.com:8042が絶対パスと絶対パスを連結することはそれほど面倒ではないようです。結局のところ、クライアントはサーバーにリクエストを送信するときに、そのスキームとドメイン名をすでに知っていますか?

全体として、絶対URIを使用することをお勧めします。おそらく、絶対パスを使用して相対URIにフォールバックし、相対パスは使用しないでください


2
これは良い答え(+1)であり、最終的な結論を除いて私は同意します。しかし、私の答えでは、HTTP仕様では、たとえば、完全修飾URIではなく、絶対パスを参照するために「絶対」が定義されていると主張しています。だから私はあなたの(2)に同意しません-それ絶対URIですが、クライアントがネットワークプロトコルとホストを推測しなければならないものなので、完全修飾URIではありません。したがって、完全URIと絶対URIの両方である(1)の定義にも同意しません。
ローレンスドル2014

コメントありがとうございます。ファイルシステムから絶対パスと相対パスの概念を借りるだけです。用語は別として、あなたの意見と私の意見の間に実質的な違いは見られません。フォーム1と2もお勧めしますが、フォーム3には反対ですよね。
RayLuo 2014

2
実際には、私は(2)のためです。(1)バックエンドには多くのHTTP固有の知識(一般的なHTTPではなく、特定のHTTP環境の詳細についての知識)が必要であり、(3)クライアントの多くが必要なようです。しかし、私の推論は元のドラフト仕様に基づいており、例は私の推論を無効にする方法で後のバージョンで変更されました。
ローレンスドル2014

個人的には、私は(まだ)HATEOASをまったく確信していません。したがって、URIを返すという要求は、APIにとってそれほど意味があります。Webサイトの閲覧に似た方法でAPIがクライアント上で駆動されているのを見ていません。ユースケースは、アドホック機能によって非常に推進されているようです。
ローレンスドル2014

@LawrenceDol最初はHATEOASについて同じ混乱があります。今、私はそれを選択の問題と考えています。クライアントはアドホック関数を使用してAPIを確実に使用できますが、必要に応じて、クライアントが従うパターンを開発できるため、クライアントは正確なURLをそれぞれハードコーディングする必要がありません。それがHATEOASです。
RayLuo 2014年

13

誰がクライアントコードを書いているかによります。クライアントとサーバーを作成している場合は、それほど大きな違いはありません。クライアントまたはサーバーでURLを作成するのに苦労するでしょう。

ただし、サーバーを構築していて、他の人がクライアントコードを書くことを期待している場合は、完全なURIを提供すれば、他の人があなたをもっと愛してくれるでしょう。相対URIの解決には少し注意が必要です。まず、それらをどのように解決するかは、返されるメディアタイプによって異なります。Htmlにはbaseタグがあり、Xmlにはネストされたすべての要素にxml:baseタグを含めることができ、Atomフィードにはフィードにbaseを、コンテンツに異なるbaseを含めることができます。クライアントにベースURIに関する明示的な情報を提供しない場合、クライアントはリクエストURIから、またはおそらくContent-LocationヘッダーからベースURIを取得する必要があります。そして、その末尾のスラッシュに注意してください。ベースURIは、最後のスラッシュの右側にあるすべての文字を無視することによって決定されます。これは、相対URIを解決するときに、末尾のスラッシュが非常に重要になることを意味します。

少し言及する必要がある他の唯一の問題は、ドキュメントのサイズです。各アイテムに複数のリンクがある可能性のあるアイテムの大きなリストを返す場合、エンティティを圧縮しないと、絶対URLを使用するとエンティティにかなりの量のバイトが追加される可能性があります。これはパフォーマンスの問題であり、ケースバイケースで重要かどうかを判断する必要があります。


11

唯一の本当の違いは、クライアントが相対バージョンから構築するのではなく、絶対URIを使用している方が簡単であるように思われるでしょう。もちろん、その違いは絶対バージョンを実行するために私を動揺させるのに十分でしょう。


7

アプリケーションの拡張に応じて、負荷分散やフェイルオーバーなどを実行することをお勧めします。絶対URIを返す場合、クライアント側アプリは進化するサーバー構成に従います。


「絶対」を絶対パス(例/xxx/yyy...)として定義し、完全修飾URI(例http://api.example.com/xxx/yyy...)を意味するものとして定義しない場合。
ローレンスドル2014

6

RayLouのトリコトミーを使用して、私の組織は(2)を支持することを選択しました。主な理由は、XSS(クロスサイトスクリプティング)攻撃を回避することです。問題は、攻撃者がサーバーから返される応答に独自のURLルートを挿入できる場合、後続のユーザー要求(ユーザー名とパスワードを使用した認証要求など)が攻撃者自身のサーバーに転送される可能性があることです*。

負荷分散のためにリクエストを他のサーバーにリダイレクトできるという問題を提起する人もいますが、(それは私の専門分野ではありませんが)クライアントを別のサーバーに明示的にリダイレクトすることなく負荷分散を有効にするより良い方法があると思いますホスト。

*この推論の行に欠陥がある場合はお知らせください。もちろん、目標はすべての攻撃を防ぐことではなく、少なくとも1つの攻撃手段を防ぐことです。


私の以前の回答があなたの組織に役立ったことをうれしく思います。はい、私は個人的にも(2)、別名スキームのない絶対パスを好みます。しかし、私はあなたの推論に興味があります。スキームのないURLのみを受け入れるようにクライアントをどのように強制しましたか?ブラウザなどの一般的なクライアントは、スキームのないURLをまったく拒否しません。したがって、実際にURLをフォローする前に、URLを検証するために独自のクライアント側コードを作成する必要があると思いますか?これは技術的には実行可能ですが(必ずしも有用ではありません)、この種のクライアント側の検証は通常、RESTまたはHATEOASの議論の一部ではありません。
RayLuo 2017年

3
これが古い投稿であることは知っていますが、「攻撃者が戻ってくる応答に独自のURLルートを挿入できる場合」は、一種のナンセンスな理由であることを指摘したいと思います。彼らが応答の正しい場所に「自分のURLを挿入」できれば、ホスト名を自分のホスト名に置き換えるのと同じくらい簡単にできると思います。したがって、セキュリティの観点から、私はそれを有効な議論とは見なしていません。
マグヌスエリクソン2018

5

常に完全なURLを使用する必要があります。URLはすべて一意である必要があるため、リソースの一意の識別子として機能します。

私はまた、あなたが一貫しているべきだと主張します。Location HTTPヘッダーはHTTP仕様に基づいて完全なURLを想定しているため、新しいリソースが作成されると、完全なURLがLocationヘッダーでクライアントに返送されます。Locationヘッダーに完全なURLを指定してから、応答本文内のリンクに相対URIを指定するのはおかしいでしょう。


1
さて、LocationヘッダーのHTTP仕様は絶対URIを示しています。絶対URIにはスキーム(httpなど)が含まれている必要があります。
マークボバー2014

しかし、問題はコンテキストのない不透明な識別子を構築する方法ではなく、リンクを構築する方法を尋ねます。後者は「このドキュメントと同じネットワークの場所にある」と正しく推測する可能性があり、それがまさに仕様のLocationヘッダーの例が示すものです。URIスキームやサーバーのネットワークの場所を含まない絶対URIです。リンクとIDはしばしば混同されますが、同じものではありません。前者にはコンテキストがあり、後者にはコンテキストがありません。
ローレンスドル2014

あなたが話している仕様の部分へのリンクを送ることができますか?
マークボバー2014

絶対URIはスキームを指定します。絶対ではないURIは相対的であると言われます。URIは、不透明か階層かによっても分類されます。不透明なURIは、スキーム固有の部分がスラッシュ文字( '/')で始まらない絶対URIです。不透明なURIは、それ以上の解析の対象にはなりません。不透明なURIの例は次のとおりです。mailto:java-net@java.sun.com news:comp.lang.java urn:isbn:096139210x
Mark Bober 2014

1
ちょっと心配しないで。このことに関するもう1つのポイントは、hrefをIDとして使用している人を見たことがあるということです。クライアントが設定ファイルとIDからURLを再構築する必要がないように、クライアントはURLを知っているだけで、それに基づいてキャッシュできます。
マークボバー2014

2

大規模なAPIの結果における重要な考慮事項は、完全なURIを繰り返し含めることによる余分なネットワークオーバーヘッドです。信じられないかもしれませんが、gzipはこの問題を完全に解決するわけではありません(理由はわかりません)。結果に何百ものリンクが含まれているときに、URI全体がどれだけのスペースを占めるかにショックを受けました。


2

絶対URIを使用することの1つの欠点は、APIをプロキシできないことです。

それを取り戻してください...真実ではありません。ドメインを含む完全なURLを取得する必要があります。


3
絶対URIがプロキシのホスト名を使用できないのはなぜですか?
エドサマーズ2012

1
現時点でこの正確な問題に取り組んでいます。すべてのリクエストは、最初に一種の「負荷分散」レイヤーを通過する必要があります。サーバーへの絶対URIは、このモデルを直接壊します。
mag382 2013年

1
Nginxを使用して絶対URLでサイトをプロキシしています。バックエンドURLを同等のプロキシURLに完全に置き換えることができます。具体的には、windyroad.artifactoryonline.com(完全修飾URLと完全修飾リダイレクトを含む)をrepo.windyroad.com.auにプロキシしています
トムハワード

2

長所に関しては、クライアントが(絶対)パスに必要とする追加の処理を犠牲にして、送信されるバイト数が減少すると思います。gzipとしてのコンテンツエンコーディング、キャッシュヘッダーの適切な使用、クライアントでのetagの使用、条件付きリクエストを試した後でも、すべてのバイトを保存したい場合は、これが最終的に必要になる可能性がありますが、あなたの努力は他にありました。

短所については、将来的にリソース間でクライアントのフローをどのように方向付けることができるか(負荷分散、A / Bテストなど)に関する制御が失われると思います。Webの管理に関しては悪い習慣だと思います。 API。指定したURLは、クライアントにとって基本的に不透明ではなくなりました(URIの不透明性に関するWebアーキテクチャのTim Berners-Lee Axiomsを参照)。最終的には、URLスペースの構造のみに関係している場合でも、APIのクリエイティブな使用に関してクライアントを満足させる責任があります。明示的に定義されたURL変更を許可する必要がある場合は、ハイパーテキストアプリケーション言語で使用されているURIテンプレートの使用を検討してください

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