417 Stimmen

Was sind bewährte Methoden für REST verschachtelte Ressourcen?

Meines Wissens nach sollte jeder einzelne Ressourcenpfad nur einen kanonischen Pfad haben. Also, in dem folgenden Beispiel, welche wären gute URL-Muster?

Nehmen wir zum Beispiel eine REST-Repräsentation von Unternehmen. In diesem hypothetischen Beispiel, besitzt jedes Unternehmen 0 oder mehr Abteilungen und jede Abteilung 0 oder mehr Mitarbeiter.

Ein Abteilung kann nicht existieren ohne ein zugehöriges Unternehmen.

Ein Mitarbeiter kann nicht existieren ohne eine zugehörige Abteilung.

Nun würde ich die natürliche Darstellung der Ressourcenmuster wie folgt finden.

  • /unternehmen Eine Sammlung von Unternehmen - Akzeptiert POST für ein neues Unternehmen. Erhalte die gesamte Sammlung.
  • /unternehmen/{unternehmensId} Ein einzelnes Unternehmen. Akzeptiert GET, PUT und DELETE
  • /unternehmen/{unternehmensId}/abteilungen Akzeptiert POST für ein neues Element. (Erstellt eine Abteilung innerhalb des Unternehmens.)
  • /unternehmen/{unternehmensId}/abteilungen/{abteilungsId}/
  • /unternehmen/{unternehmensId}/abteilungen/{abteilungsId}/mitarbeiter
  • /unternehmen/{unternehmensId}/abteilungen/{abteilungsId}/mitarbeiter/{maId}

Unter Berücksichtigung der Einschränkungen, fühlt sich jede dieser Abschnitte für mich schlüssig an, wenn auch etwas tief genestet.

Allerdings habe ich Schwierigkeiten, wenn ich alle Mitarbeiter über alle Unternehmen auflisten möchte (GET).

Das Ressourcenmuster dafür würde am ehesten zu /mitarbeiter (Die Sammlung aller Mitarbeiter) passen

Bedeutet das, dass ich auch /mitarbeiter/{maId} haben sollte, weil wenn ja, gibt es dann zwei URIs, um die gleiche Ressource abzurufen?

Oder vielleicht sollte das gesamte Schema abgeflacht werden, aber das würde bedeuten, dass Mitarbeiter ein verschachteltes Top-Level-Objekt sind.

Auf einer grundlegenden Ebene gibt /mitarbeiter/?unternehmen={unternehmensId}&abteilung={abteilungsId} die genau gleiche Ansicht der Mitarbeiter wie das am tiefsten verschachtelte Muster zurück.

Was ist die bewährte Praxis für URL-Muster, bei denen Ressourcen von anderen Ressourcen besessen werden, aber separat abgefragt werden sollen?

14voto

redben Punkte 5390

Wie Ihre URLs aussehen, hat nichts mit REST zu tun. Alles ist erlaubt. Es handelt sich tatsächlich um ein "Implementierungsdetail". Genau wie bei der Benennung Ihrer Variablen. Sie müssen nur eindeutig und dauerhaft sein.

Verschwenden Sie nicht zu viel Zeit damit, treffen Sie einfach eine Wahl und bleiben Sie dabei/konsistent. Zum Beispiel, wenn Sie sich für Hierarchien entscheiden, dann tun Sie dies für alle Ihre Ressourcen. Wenn Sie sich für Query-Parameter entscheiden...etc. genau wie Namenskonventionen in Ihrem Code.

Warum so ? Soweit ich weiß, sollte eine "RESTful" API durchsuchbar sein (Sie wissen... "Hypermedia als Motor des Anwendungszustands"), daher ist es einem API-Client egal, wie Ihre URLs aussehen, solange sie gültig sind (es gibt kein SEO, kein Mensch, der diese "freundlichen URLs" lesen muss, außer vielleicht zum Debuggen...)

Wie schön/verständlich eine URL in einer REST-API ist, interessiert nur Sie als API-Entwickler, nicht den API-Client, genauso wenig wie der Name einer Variablen in Ihrem Code.

Das Wichtigste ist, dass Ihr API-Client weiß, wie er Ihren Medientyp interpretieren soll. Beispielsweise weiß er, dass :

  • Ihr Medientyp eine Links-Eigenschaft hat, die verfügbare/verwandte Links auflistet.
  • Jeder Link wird durch eine Beziehung identifiziert (genau wie Browser wissen, dass link[rel="stylesheet"] bedeutet, dass es sich um ein Stylesheet handelt oder rel=favico ein Link zu einem Favicon ist...)
  • und er weiß, was diese Beziehungen bedeuten ("Unternehmen" bedeutet eine Liste von Unternehmen, "Suche" bedeutet eine vorgegebene URL für die Suche in einer Liste von Ressourcen, "Abteilungen" bedeutet Abteilungen der aktuellen Ressource )

Hier ist ein Beispiel für einen HTTP-Austausch (die Bodies sind in YAML geschrieben, da es einfacher ist):

Anfrage

GET / HTTP/1.1
Host: api.acme.io
Accept: text/yaml, text/acme-mediatype+yaml

Antwort: eine Liste von Links zur Hauptressource (Unternehmen, Personen, was auch immer...)

HTTP/1.1 200 OK
Date: Di, 05 Apr 2016 15:04:00 GMT
Last-Modified: Di, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml

# Body: Dies ist der Einstiegspunkt Ihrer API (wie eine Homepage)  
links:
  # könnte ein zufälliger Pfad sein https://api.acme.local/modskmklmkdsml
  # das Einzige, worum sich der API-Client kümmert, ist der Schlüssel (oder rel) "Unternehmen"
  companies: https://api.acme.local/companies
  people: https://api.acme.local/people

Anfrage: Link zu Unternehmen (Verwendung des vorherigen Antwort-Body.links.companies)

GET /companies HTTP/1.1
Host: api.acme.local
Accept: text/yaml, text/acme-mediatype+yaml

Antwort: eine Teilliste von Unternehmen (unter Elemente), die Ressource enthält verwandte Links, wie den Link, um die nächsten Unternehmen abzurufen (body.links.next) und einen anderen (vorgegebenen) Link für die Suche (body.links.search)

HTTP/1.1 200 OK
Date: Di, 05 Apr 2016 15:06:00 GMT
Last-Modified: Di, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml

# Body: Darstellung einer Liste von Unternehmen
links:
  # Link zur nächsten Seite
  next: https://api.acme.local/companies?page=2
  # vorgegebener Link für die Suche
  search: https://api.acme.local/companies?query={query} 
# Sie könnten verfügbare Aktionen im Zusammenhang mit dieser Ressource angeben
actions:
  add:
    href: https://api.acme.local/companies
    method: POST
items:
  - name: Unternehmensname1
    links:
      selbst: https://api.acme.local/companies/8er13eo
      # und hier ist der Link zu Abteilungen
      # wiederum interessiert sich der Client nur für das Schlüsselwort Abteilung
      department: https://api.acme.local/companies/8er13eo/departments
  - name: Unternehmensname2
    links:
      selbst: https://api.acme.local/companies/9r13d4l
      # oder könnte an einem anderen Ort sein ! 
      department: https://api2.acme.local/departments?company=8er13eo

Wie Sie sehen, wenn Sie den Weg der Links/Beziehungen gehen, hat die Struktur des Pfadteils Ihrer URLs keinen Wert für Ihren API-Client. Und wenn Sie die Struktur Ihrer URLs als Dokumentation an Ihren Client übermitteln, dann handeln Sie nicht nach REST (oder zumindest nicht nach Level 3 gemäß "Richardsons Reifegradmodell")

3voto

partydrone Punkte 467

Rails bietet eine Lösung dafür: shallow nesting.

Ich denke, das ist gut, weil wenn man direkt mit einer bekannten Ressource arbeitet, keine Notwendigkeit besteht, verschachtelte Routen zu verwenden, wie es in anderen Antworten hier diskutiert wurde.

2voto

user566245 Punkte 3514

Gemäß der Dokumentation des Django Rest Frameworks:

Im Allgemeinen empfehlen wir einen flachen Stil für API-Repräsentationen, wo immer möglich, aber der verschachtelte URL-Stil kann auch vernünftig sein, wenn er in Maßen verwendet wird.

https://www.django-rest-framework.org/api-guide/relations/#example_2

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X