web-dev-qa-db-ja.com

RESTful API-サブリソースの設計

RESTful APIを設計していますが、サブリソースに関連する問題が発生しました。

完全なURLを使用してサブリソースを操作する他のAPIを確認しました。 Company has DepartmentsおよびDepartment has Employees

初めに私は考えられるすべてのURLの実装について考えました。次の結果:

アプローチA

01. ### COMPANY URLS ###
02. DELETE /companies/{companyId}
03. GET    /companies/{companyId}
04. POST   /companies
05. PUT    /companies/{companyId}
06. 
07. ### DEPARTMENT URLS ###
08. DELETE /companies/{companyId}/departments/{departmentId}
09. GET    /companies/{companyId}/departments/{departmentId}
10. POST   /companies/{companyId}/departments
11. PUT    /companies/{companyId}/departments/{departmentId}
12. DELETE /departments/{departmentId}
13. GET    /departments/{departmentId}
14. PUT    /departments/{departmentId}
15. 
16. ### EMPLOYEE URLS ###
17. DELETE /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
18. GET    /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
19. POST   /companies/{companyId}/departments/{departmentId}/employees
20. PUT    /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
21. DELETE /departments/{departmentId}/employees/{employeeId}
22. GET    /departments/{departmentId}/employees/{employeeId}
23. POST   /departments/{departmentId}/employees
24. PUT    /departments/{departmentId}/employees/{employeeId}
25. DELETE /employees/{employeeId}
26. GET    /employees/{employeeId}
27. PUT    /employees/{employeeId}

ご覧のとおり、同じことを行うURLはたくさんあります。例:08は12の複製です。 09は13の複製です。 17は21と25の複製です...

重複を取り除き、一貫性を保ちたい。そこで、原則を念頭に置いてAPIを再設計しましたsup-resources are fine but sub-sub-resources are not。その結果、次のようになりました。

アプローチB

01. ### COMPANY URLS ###
02. DELETE /companies/{companyId}
03. GET    /companies/{companyId}
04. POST   /companies
05. PUT    /companies/{companyId}
06. 
07. ### DEPARTMENT URLS ###
08. DELETE /departments/{departmentId}
09. GET    /departments/{departmentId}
10. GET    /companies/{companyId}/departments
11. POST   /companies/{companyId}/departments
12. PUT    /departments/{departmentId}
13. 
14. ### EMPLOYEE URLS ###
15. DELETE /employees/{employeeId}
16. GET    /employees/{employeeId}
17. GET    /departments/{departmentId}/employees
18. POST   /departments/{departmentId}/employees
19. PUT    /employees/{employeeId}

私の質問

Q1。 アプローチB RESTfulと見なされますか?(私はイエスと想定しています)

Q2。落とし穴はありますかアプローチBドキュメントも提供されていると想定して、私は考慮すべきですか?

アプローチBに従って他のAPIをポイントするとボーナスポイントが発生します。

[〜#〜]編集[〜#〜]

Elad Tabakは良い洞察を示しました。

アプローチBを使用していくつかのAPIが好きです:

https://developers.google.com/youtube/v3/docs/

https://developer.github.com/guides/getting-started/

https://dev.Twitter.com/rest/public

20
Rafa

Roy Thomas Fieldingの論文の​​ 第5章 で定義されているREST制約を破らない限り、両方のアプローチはRESTfulと見なすことができます。

どちらのアプローチでも大きな落とし穴は見られませんが、-アプローチAよりもアプローチBのほうがいいと思います。URLは短く、覚えやすく、多くのパラメーターは必要ありません。


ボーナスポイント:Spotify および Facebook APIはこのアプローチに従います。確かに他のAPIもありますが、これらは私の頭に浮かんだものです。

7
cassiomolin

設計アプローチでは、2つを選択するときに考慮する必要があるいくつかの質問が生じます。

存在依存関係

[〜#〜] a [〜#〜]の場合、非常に直感的であり、会社を削除すると、そのすべてのサブリソース(部門と従業員)も削除されます。 [〜#〜] b [〜#〜]では、APIユーザーはそのようなアクションについて少し考える必要があります-すべての従業員に対して削除を呼び出す必要がありますか、それとも会社を削除するのに十分ですか? ?もちろん、これは文書化できますが、それでも簡単ではありません。

[〜#〜] a [〜#〜]これは非常に明確であるため、ここに利点があります。リソースを削除すると、そのサブリソースのすべてが削除されます。

操作のエンドポイント

それが提起する別の質問-エンティティを更新するにはどうすればよいですか?どのエンドポイントから?

従業員を削除する場合、新しい従業員のセットで会社を更新するだけで十分ですか?または従業員を削除する必要がありますか?

または、従業員をある会社から別の会社に変更したいと言います。 [〜#〜] b [〜#〜]では、理論的には会社フィールドで従業員を更新し、それで終了できます。 [〜#〜] a [〜#〜]にはそのような方法はありません...

[〜#〜] a [〜#〜]は、アクションを実行する方法が非常に単純であるという利点があります-エンティティURLに対するCRUD。 [〜#〜] b [〜#〜]は、APIユーザーを停止し、ユーザーがどのURLでどのアクションを実行できるかを疑問に思います。

ただし、同時に[〜#〜] b [〜#〜]には、エンティティの「親子関係」を変更する方が簡単であるという利点があります(関連する場合)。

検証

[〜#〜] a [〜#〜]では、ユーザーが間違った会社または部門の従業員IDを提供できるため、URL引数の一致を検証する必要があります。 [〜#〜] b [〜#〜]では、そのような問題はありません。

5
Elad Tabak
  1. RESTはURLの設計について何も述べていません。思いつくURLスキームはすべてRESTfulです。それが良いデザインかどうか尋ねるべきです。そして、はい、2番目のアプローチは最初のアプローチよりも非常に望ましいです。最初の問題は、クライアントにとっては膨大なノイズであり、所有者にとってはメンテナンスの大きな問題です。また、将来の柔軟性も制限されます。

  2. エンドポイントの使用方法を明確に文書化している限り、私が認識している重大な落とし穴はありません。たとえば、ネストされたエンドポイントは関連する要素のみを返すのが一般的です。ネストされた要素を削除すると、関連付けのみが削除され、要素自体は削除されません。この種の動作は、何らかの方法で文書化する必要があります。

ボーナスポイント:外部リソースを要求することは範囲外です。

5
Eric Stein

したがって、これは少し気違いに聞こえるかもしれませんが、HTTP/RESTには「サブリソース」のようなものはありません。

ドメインモデルでは、部署は会社なしでは存在できません。

次に、APIで、/companies/{companyId}に会社のjson表現を、/companies/{companyId}/departments/{departmentId}に部門のjson表現を公開します。

これらは両方とも「リソース」です。リソースは、HTTP/REST用語では、URLが指すものを意味します。したがって、それは会社自体ではなく「会社のjson表現」です。

URLの設計自体は、それ自体が少し行き止まりの路地です。URL自体は何にでも似ている可能性があり、読み取り可能かどうかは関係ありません。開発者は、ドキュメント*の操作名に応じてURLを選択し、リクエストを行います。 URL自体に意味を追加しようとするとすぐにトリッキーになり、実際には時間が経つにつれ混乱が生じる可能性があります。

ドメインの振る舞いについて人々に推測させようとするよりも、ドキュメントに時間を費やすほうがよいでしょう。

*またはハイパーメディア(例 https://github.com/kevinswiber/siren

4
mcintyre321