web-dev-qa-db-ja.com

REST-複数の可能な識別子をサポート

私が取り組んでいるサイトでは、1つのタイプのリソースのURLを改善する作業を行っています。具体的には、数値IDから一意の説明的な文字列に移行しています。同様の例は、数値データベースIDによるユーザーの識別から、ユーザー名によるユーザーの識別に切り替えます(特定のケースではなく、類似しています)。したがって、ユーザーの情報にアクセスするためのURLは次のようになります。

/users/48573

そして今それは

/users/thisisausername.

唯一の問題は、APIのレガシーコンシューマーのために、数値IDを介してそれらをフェッチできるようにする必要があることです。 REST URL自体をリダイレクトする必要はありません(たとえば、/users/48573/users/thisisausernameにリダイレクトしないでください)。必要なのは、古い識別子。ソリューションは、IDでユーザー情報(新しい識別子、ユーザー名を含む)にアクセスする、またはIDでユーザー名のみにアクセスする別の方法を提供する必要があります。

  • ノードを使用して、別の識別方法を指定します。 /users/byid/48573
  • クエリパラメータを使用して、別の識別方法を指定します。 /users/48573?fetchby=idまたは/users/48573?byid=true
  • Username-by-idを別のリソースとして扱う。 /identifiers/username/48573

これらのうちどれが適切なRESTに最も近いですか?どのように問題に対処しますか?

54
Kelly Ellis

パスセグメント/プレフィックスを追加するのが最良の答えだと思います。これらは一意のセカンダリキーであるため、これは検索(アイテムのセットを返す)と同じではないため、(キャッシュされていない)クエリパラメーターを使用するのは最善の選択ではないようです。

個人的には、「name =」や「email =」のように、「=」で区切られたパスセグメントプレフィックスを使用する予定です。

user/123456
user/name=john.doe
user/[email protected]

これは、機能的にはパスセグメントを追加することと同じです(例: "user/name/john.doe")。概念モデルにより近くマッピングされているように感じます。もちろん、RESTful APIは固定URI構造を指定するべきではないので、これは重要ではない詳細です。

クエリパラメータを使用しないと、サブリソースに自然にアクセスできます。

user/name=john.doe/inbox/df87bhJXrg63

JavaのJAX-RSなどのフレームワークは、任意の区切り文字を使用してサポートします。

@GET
@Path("user/{id}")
User getUser(@PathParam("id") UUID id);

@GET
@Path("user/name={name}")
User getUserByName(@PathParam("name") String name);

@GET
@Path("user/email={email}")
User getUserByEmail(@PathParam("email") String email);
32
Trevor Robinson

あなたの最初のオプションはおそらく最高です。

IDによるユーザーの検索:

/users/id/48573

短い名前でユーザーを検索する:

/users/name/thisisausername

彼らがそのパスパラメータを省略した場合、常にデフォルトで新しい短いユーザー名の形式にすることができます。

私がかなり多く見たもう1つのオプションは、次のようなクエリパラメータを使用することです。

/users?id=48573
/users?name=thisisausername

最初のものは少しすっきりとして読みやすくなっていると思います。

17
Chris Dail

かなり古い質問ですが、同じことがあり、最終的に解決策が見つかりました。パスパラメータで正規表現を使用してください。

これが私がそのユースケースをコーディングした方法です

@GET
@Path("/{id : \\d+}")
@Produces(APPLICATION_JSON)
public Response getById(@PathParam("id") long id) {
 <<your code>>
}

@GET
@Path("/{name}")
@Produces(APPLICATION_JSON)
public Response getByName(@PathParam("name") String name) {
 <<your code>>
}
0
Javathought