it-swarm.com.de

Eine Webanwendung als REST API-Client: Umgang mit Ressourcenkennungen

Verschiedene Konzepte im Zusammenhang mit REST Konflikt in meinem Kopf, wenn ich versuche, es zu implementieren.

Ich habe ein REST-volles Back-End-API-System, das die Geschäftslogik enthält, und eine Webanwendung, die die Benutzeroberfläche bereitstellt. Aus verschiedenen Quellen zu REST (insbesondere REST in der Praxis: Hypermedia- und Systemarchitektur ) weiß ich, dass ich keine rohen Bezeichner meiner Entitäten verfügbar machen sollte, sondern Hyperlinks zurückgeben sollte mit rel="self".

Betrachten Sie das Beispiel. Die REST API) hat eine Ressource, die eine Person zurückgibt:

<Person>
  <Links>
    <Link rel="self" href="http://my.rest.api/api/person/1234"/>
  </Links>
  <Pets>
    <Link rel="pet" href="http://my.rest.api/api/pet/678"/>
  </Pets>
</Person>

Das Problem tritt bei der Webanwendung auf. Nehmen wir an, es wird eine Seite zurückgegeben, die einen Hyperlink zu Browsern enthält:

<body class="person">
  <p>
    <a href="http://my.web.app/pet/???????" />
  </p>
</body>

Was soll ich in das Attribut href einfügen? Wie behalte ich die API-Entitäts-URL in der Webanwendung, um die Entität abrufen zu können, wenn ein Benutzer die Zielseite öffnet?

Die Anforderungen scheinen widersprüchlich:

  1. Der Hyperlink href sollte zur Webanwendung führen, da es sich um das System handelt, auf dem sich die Benutzeroberfläche befindet
  2. Das href sollte eine ID der Entität haben, da die Webanwendung in der Lage sein muss, die Entität beim Öffnen der Zielseite zu adressieren
  3. Die Web-App sollte nicht analysieren/konstruieren REST URLs, da sie nicht REST-voll sind, heißt es in dem erwähnten Buch

URIs sollten für Verbraucher undurchsichtig sein. Nur der Aussteller des URI kann ihn interpretieren und einer Ressource zuordnen.

Also kann ich nicht einfach 1234 von der API-Antwort-URL, da ich sie als RESTful-Client so behandeln sollte, als wäre es so etwas wie http://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j. Andererseits muss ich eine URL angeben, die zu meiner Web-App führt und ausreicht, damit die App die ursprüngliche URL der API irgendwie wiederherstellt und diese URL für den Zugriff auf die API-Ressourcen verwendet.

Der einfachste Weg besteht wahrscheinlich darin, nur die API-URLs von Ressourcen als Zeichenfolgenkennungen zu verwenden. Aber Webseiten-URLs wie http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234 sind hässlich.

Für eine Desktop-App oder eine einseitige Javascript-App scheint alles recht einfach zu sein. Da sie kontinuierlich leben, können sie einfach die URLs zusammen mit den Serviceobjekten für die Anwendungslebensdauer im Speicher behalten und sie bei Bedarf verwenden.

Mit einer Web-App kann ich mir verschiedene Ansätze vorstellen, aber alle scheinen seltsam:

  1. Ersetzen Sie den Host in den API-URLs und behalten Sie nur das Ergebnis bei. Der große Nachteil ist, dass die Webanwendung die von der API generierte URL verarbeiten muss, was eine monströse Kopplung bedeutet. Außerdem ist es nicht wieder RESTful, da meine Web-App die URLs interpretiert.
  2. Stellen Sie die unformatierten IDs in der API REST API zusammen mit den Links bereit), verwenden Sie sie zum Erstellen der URLs der Web-App und verwenden Sie dann die IDs auf dem Web-App-Server, um die erforderlichen Ressourcen in der API zu finden ist besser, wirkt sich jedoch auf die Leistung des Web-App-Servers aus, da die Web-App die Dienstnavigation REST) durchlaufen muss, um eine Kette von Get-by-ID-Anforderungen in irgendeiner Form auszugeben und alle Anforderungen zu bearbeiten Für eine etwas verschachtelte Ressource kann dies kostspielig sein.
  3. Speichern Sie alle von der API zurückgegebenen self-URLs in einer dauerhaften (DB?) Zuordnung auf dem Web-App-Server. Generieren Sie einige IDs für sie, verwenden Sie die IDs, um die URLs der Web-App-Seite zu erstellen und die URLs der REST Service-Ressourcen) abzurufen. Das heißt, ich behalte die http://my.rest.api/pet/678 URL irgendwo mit einem neuen Schlüssel, sagen wir 3 und generieren Sie die Webseiten-URL als http://my.web.app/pet/3. Dies sieht aus wie eine Art HTTP-Cache-Implementierung. Ich weiß nicht warum, aber es kommt mir komisch vor.

Oder Bedeutet das alles, dass RESTful-APIs nicht als Backend für Webanwendungen dienen können?

21
Pavel Gatilov

Bearbeitet, um Fragenaktualisierungen zu adressieren, vorherige Antwort entfernt

Wenn ich mir Ihre Änderungen an Ihrer Frage ansehe, verstehe ich das Problem, mit dem Sie konfrontiert sind, etwas besser. Da Ihre Ressourcen kein Feld enthalten, das eine Kennung darstellt (nur ein Link), können Sie in Ihrer GUI nicht auf diese bestimmte Ressource verweisen (d. H. Auf einen Link zu einer Seite, die ein bestimmtes Haustier beschreibt).

Als Erstes muss festgestellt werden, ob ein Haustier ohne Besitzer jemals Sinn macht. Wenn wir ein Haustier ohne Besitzer haben können, würde ich sagen, dass wir eine einzigartige Eigenschaft für das Haustier benötigen, mit der wir uns darauf beziehen können. Ich glaube nicht, dass dies gegen das Nicht-Offenlegen der ID verstoßen würde, da die tatsächliche Ressourcen-ID immer noch in einem Link versteckt wäre, den der REST - Client nicht analysieren würde. In diesem Sinne unsere Haustierressource kann aussehen wie:

<Entity type="Pet">
    <Link rel="self" href="http://example.com/pets/1" />
    <Link rel="owner" href="http://example.com/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

Wir können jetzt den Namen dieses Haustieres von Spot auf Fido aktualisieren, ohne uns mit den tatsächlichen Ressourcen-IDs in der gesamten Anwendung herumschlagen zu müssen. Ebenso können wir auf dieses Haustier in unserer GUI mit etwas verweisen wie:

http://example.com/GUI/pets/Spot

Wenn das Haustier ohne Besitzer keinen Sinn ergibt (oder Haustiere ohne Besitzer nicht im System erlaubt sind), können wir den Besitzer als Teil der "Identität" des Haustieres im System verwenden:

http://example.com/GUI/owners/John/pets/1 (erstes Haustier in der Liste für John)

Ein kleiner Hinweis: Wenn sowohl Haustiere als auch Personen getrennt voneinander existieren können, würde ich den Einstiegspunkt für die API nicht zur Ressource "Personen" machen. Stattdessen würde ich eine allgemeinere Ressource erstellen, die einen Link zu Personen und Haustieren enthält. Es könnte eine Ressource zurückgeben, die wie folgt aussieht:

<Entity type="ResourceList">
    <Link rel="people" href="http://example.com/api/people" />
    <Link rel="pets" href="http://example.com/api/pets" />
</Entity>

Wenn wir also nur den ersten Einstiegspunkt in die API kennen und keine der URLs verarbeiten, um Systemkennungen herauszufinden, können wir Folgendes tun:

Benutzer meldet sich bei der Anwendung an. Der Client REST] greift auf die gesamte Liste der verfügbaren Personenressourcen zu, die wie folgt aussehen können:

<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/1" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/1" />
        <Link rel="pet" href="http://example.com/api/pets/2" />
    </Pets>
    <UniqueName>John</UniqueName>
</Entity>
<Entity type="Person">
    <Link rel="self" href="http://example.com/api/people/2" />
    <Pets>
        <Link rel="pet" href="http://example.com/api/pets/3" />
    </Pets>
    <UniqueName>Jane</UniqueName>
</Entity>

Die GUI durchläuft jede Ressource und druckt ein Listenelement für jede Person aus, wobei der eindeutige Name als "ID" verwendet wird:

<a href="http://example.com/gui/people/1">John</a>
<a href="http://example.com/gui/people/2">Jane</a>

Dabei könnte es auch jeden gefundenen Link mit einem rel von "pet" verarbeiten und die Haustierressource abrufen, wie zum Beispiel:

<Entity type="Pet">
    <Link rel="self" href="http://example.com/api/pets/1" />
    <Link rel="owner" href="http://example.com/api/people/1" />
    <UniqueName>Spot</UniqueName>
</Entity>

Damit kann ein Link gedruckt werden wie:

<!-- Assumes that a pet can exist without an owner -->
<a href="http://example.com/gui/pets/Spot">Spot</a>

oder

<!-- Assumes that a pet MUST have an owner -->
<a href="http://example.com/gui/people/John/pets/Spot">Spot</a>

Wenn wir mit dem ersten Link gehen und annehmen, dass unsere Eingaberessource einen Link mit einer Beziehung von "Haustieren" hat, würde der Kontrollfluss in der GUI ungefähr so ​​aussehen:

  1. Die Seite wird geöffnet und der Haustier-Spot wird angefordert.
  2. Laden Sie die Liste der Ressourcen vom API-Einstiegspunkt.
  3. Laden Sie die Ressource, die mit dem Begriff "Haustiere" zusammenhängt.
  4. Durchsuchen Sie jede Ressource in der Antwort "Haustiere" und finden Sie eine, die mit Spot übereinstimmt.
  5. Zeigen Sie die Informationen für Spot an.

Die Verwendung des zweiten Links wäre eine ähnliche Ereigniskette mit der Ausnahme, dass Personen der Einstiegspunkt in die API ist und wir zuerst eine Liste von erhalten würden Alle Personen im System suchen die passende Person, suchen dann alle Haustiere, die zu dieser Person gehören (verwenden Sie erneut das rel-Tag), und suchen Sie die Person mit dem Namen Spot, damit wir die spezifischen Informationen dazu anzeigen können.

5
Mike

Bedeutet das alles, dass RESTful-APIs nicht als Backend für Webanwendungen dienen können?

Ich frage mich, ob es sich lohnt, zwischen einer REST API und einer Webanwendung) zu unterscheiden. Ihre "Webanwendung" sollte nur eine alternative (HTML) Darstellung derselben Ressourcen sein - das heißt, ich Verstehe nicht, wie oder warum du auf http://my.rest.api/... und http://my.web.app/... zugreifen willst und dass sie gleichzeitig gleich und verschieden sind.

Ihr "Client" ist in diesem Fall der Browser und versteht HTML und JavaScript. Das ist die Webanwendung meiner Meinung nach. Jetzt können Sie anderer Meinung sein und denken, dass Sie über foo.com auf diese Webanwendung zugreifen und alles andere über api.foo.com verfügbar machen - aber Sie müssen sich dann fragen, wie foo.com mir die Darstellung der Ressource zur Verfügung gestellt hat. Das "Back-End" von foo.com ist perfekt in der Lage zu verstehen, wie Ressourcen von api.foo.com entdeckt werden. Ihre Webanwendung ist lediglich ein Proxy geworden - nicht anders, als wenn Sie alle zusammen mit einer anderen API (von jemand anderem) gesprochen hätten.

Ihre Frage kann also verallgemeinert werden: "Wie kann ich Ressourcen mithilfe meiner eigenen URIs beschreiben, die in anderen Systemen vorhanden sind?" Das ist trivial, wenn man bedenkt, dass nicht der Client (HTML/JavaScript) verstehen muss, wie das geht, sondern der Server. Wenn Sie mit meiner ersten Herausforderung einverstanden sind, können Sie sich Ihre Webanwendung einfach als separate REST API vorstellen, die Proxys an eine andere REST API) delegiert oder delegiert.

Wenn Ihr Client auf my.web.app/pets/1 Zugreift, kann er die Haustierschnittstelle anzeigen, da dies entweder von der serverseitigen Vorlage zurückgegeben wurde oder wenn es sich um eine asynchrone Anforderung für eine andere Darstellung (z. B. JSON oder XML) handelt, den Inhalt -type Header sagt es so.

Der Server, der dies bereitstellt, ist dafür verantwortlich, zu verstehen, was ein Haustier ist und wie ein Haustier auf dem Remote-System erkannt wird. Wie Sie dies tun, liegt bei Ihnen - Sie können einfach die ID nehmen und einen anderen URI generieren, was Ihrer Meinung nach unangemessen ist, oder Sie können über eine eigene Datenbank verfügen, in der der Remote-URI gespeichert und die Anforderung weitergeleitet wird. Das Speichern dieser URI ist in Ordnung - dies entspricht dem Lesezeichen. Sie würden dies alles nur tun, um einen separaten Domainnamen zu haben. Ich weiß ehrlich gesagt nicht, warum Sie das wollen - Ihre REST API-URIs müssen auch Lesezeichen enthalten können.

Sie haben das meiste davon bereits in Ihrer Frage angesprochen, aber ich glaube, Sie haben es so gestaltet, dass es wirklich nicht anerkannt hat, dass es die praktische Art ist, das zu tun, was Sie tun möchten (basierend auf dem, was ich für eine halte willkürliche Einschränkung - dass die API und die Anwendung getrennt sind). Wenn Sie fragen, ob REST APIs keine Back-Ends für Webanwendungen sein können, und vorschlagen, dass die Leistung ein Problem darstellt, konzentrieren Sie sich auf die falschen Dinge. Es ist, als würden Sie es sagen Ich kann kein Mashup erstellen. Es ist, als würde man sagen, dass das Web nicht funktioniert.

6
Doug

Vorwort

Diese Antwort befasst sich speziell mit der Frage, wie Sie Ihr eigenes URL-Schema verwalten können, einschließlich eindeutiger Lesezeichen-URLs für Ressourcen, für die das Back-End REST API keinen Bezeichner explizit verfügbar macht, und ohne die URLs zu interpretieren von der API bereitgestellt.


Die Auffindbarkeit erfordert ein gewisses Maß an Wissen. Hier ist meine Sicht auf ein reales Szenario:

Angenommen, wir möchten eine Suchseite unter http://my.web.app/person, Auf der die Ergebnisse für jede Person einen Link zur Detailseite enthalten. Das einzige, was unser Front-End-Code muss wissen muss, um überhaupt etwas zu tun, ist die Basis-URL für seine REST-Datenquelle: http://my.rest.api/api. Die Antwort auf eine GET-Anfrage an diese URL könnte sein:

<Links>
    <Link ref="self" href="http://my.rest.api/api" />
    <Link rel="person" href="http://my.rest.api/api/person" />
    <Link rel="pet" href="http://my.rest.api/api/pet" />
</Links>

Da wir beabsichtigen, eine Liste von Personen anzuzeigen, senden wir als nächstes eine GET -Anforderung an die href vom person -Link href, die möglicherweise Folgendes zurückgibt:

<Links>
    <Link ref="self" href="http://my.rest.api/api/person" />
    <Link rel="search" href="http://my.rest.api/api/person/search" />
</Links>

Wir möchten Suchergebnisse anzeigen, daher verwenden wir den Suchdienst, indem wir eine GET - Anfrage an den search Link href senden, die möglicherweise Folgendes zurückgibt:

<Persons>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/1"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/10"/>
        </Pets>
    </Person>
    <Person>
        <Links>
            <Link rel="self" href="http://my.rest.api/api/person/2"/>
        </Links>
        <Pets>
            <Link rel="pet" href="http://my.rest.api/api/pet/20"/>
        </Pets>
    </Person>
</Persons>

Wir haben endlich unsere Ergebnisse, aber wie erstellen wir unsere Front-End-URLs?

Lassen Sie uns den Teil entfernen, den wir mit Sicherheit kennen: die API-Basis-URL, und den Rest als Front-End-ID verwenden:

  • bekannte API-Basis: http://my.rest.api/api
  • angegebene URL für einzelne Entität: http://my.rest.api/api/person/1
  • eindeutige ID: /person/1
  • unsere Basis-URL: http://my.web.app
  • unsere generierte Frontend-URL: http://my.web.app/person/1

Unsere Ergebnisse könnten folgendermaßen aussehen:

<ul>
    <li><a href="http://my.web.app/person/1">A person</a></li>
    <li><a href="http://my.web.app/person/2">A person</a></li>
</ul>

Wenn ein Benutzer diesem Front-End-Link zur Detailseite folgt, an welche URL senden wir die Anforderung GET für Details zu diesem bestimmten person? Wir kennen unsere Methode zum Zuordnen von Back-End-URLs zu Front-End-URLs, daher kehren wir sie einfach um:

  • frontend-URL: http://my.web.app/person/1
  • unsere Basis-URL: http://my.web.app
  • eindeutige ID: /person/1
  • bekannte API-Basis: http://my.rest.api/api
  • generierte API-URL: http://my.rest.api/api/person/1

Wenn sich die REST API so ändert, dass eine person URL jetzt http://my.rest.api/api/different-person-base/person/1 Ist und jemand zuvor http://my.web.app/person/1 Mit einem Lesezeichen versehen hat, wird die REST-API sollte (zumindest zeitweise) Abwärtskompatibilität bieten, indem sie auf die alte URL mit einer Umleitung auf die neue antwortet. Alle generierten Front-End-Links würden die neue Struktur automatisch enthalten.

Wie Sie wahrscheinlich bemerkt haben, müssen wir einige Dinge wissen, um in der API zu navigieren:

  • die API-Basis-URL
  • die person Beziehung
  • die search Beziehung

Ich glaube nicht, dass daran etwas falsch ist. Wir gehen zu keinem Zeitpunkt von einer bestimmten URL-Struktur aus, daher kann sich die Struktur der Entitäts-URL http://my.rest.api/api/person/1 ändern. Solange die API Abwärtskompatibilität bietet, funktioniert unser Code weiterhin.


Sie haben gefragt, wie unsere Routing-Logik den Unterschied zwischen zwei Front-End-URLs erkennen kann:

  • http://my.rest.api/api/person/1
  • http://my.rest.api/api/pet/3.

Zuerst möchte ich darauf hinweisen, dass Sie die API-Basis in Ihrem Kommentar verwendet haben, wenn wir in unserem Beispiel separate Basis-URLs für die Benutzeroberfläche und REST API) verwenden. Ich werde das Beispiel fortsetzen Die Verwendung separater Basen, aber die gemeinsame Nutzung einer Basis ist kein Problem. Wir können (oder sollten) UI-Routing-Methoden mithilfe des Medientyps aus dem Accept-Header der Anforderung zuordnen.

Beim Weiterleiten an eine bestimmte Detailseite können wir diese beiden URLs nicht unterscheiden, wenn wir strikt darauf achten, keine Kenntnisse über die Struktur der von der API bereitgestellten self-URL (d. H. Der undurchsichtigen Zeichenfolgen-ID) zu vermeiden. Damit dies funktioniert, fügen wir eine weitere unserer bekannten Informationen - den Entitätstyp, mit dem wir arbeiten - in unsere Front-End-URLs ein.

Zuvor hatten unsere Front-End-URLs das folgende Format: ${UI base}/${opaque string id}

Das neue Format könnte sein: ${UI base}/${entity type}/${opaque string id}

Wenn wir also das Beispiel /person/1 Verwenden, erhalten wir http://my.web.app/person/person/1.

Mit diesem Format würde unsere UI-Routing-Logik mit /person/person/1 Arbeiten. Da wir wissen, dass das erste Token in der Zeichenfolge von uns selbst eingefügt wurde, können wir es herausziehen und an die entsprechende Person weiterleiten (in diesem Beispiel). Detailseite basierend darauf. Wenn Sie sich über diese URL verlegen fühlen, können wir dort etwas mehr einfügen. vielleicht: http://my.web.app/person/detail/person/1

In diesem Fall würden wir den /person/detail Für das Routing analysieren und den Rest als undurchsichtige Zeichenfolgen-ID verwenden.


Ich denke, dies führt zu einer extrem engen Kopplung der Web-App an die API.

Ich vermute, Sie meinen, da unsere generierte Front-End-URL einen Teil der API-URL enthält, benötigen wir eine Codeänderung, wenn sich die API-URL-Struktur ändert, ohne die alte Struktur zu unterstützen, um die mit Lesezeichen versehene URL in die zu übersetzen neue Version der API-URL. Mit anderen Worten, wenn die REST API die ID einer Ressource (die undurchsichtige Zeichenfolge) ändert), können wir nicht mit dem Server über diese Ressource unter Verwendung der alten ID sprechen. Ich glaube nicht kann eine Codeänderung in dieser Situation vermeiden.

Was wäre, wenn ich wollte, dass sich die URL-Struktur für die Web-App von der der API unterscheidet?

Sie können eine beliebige URL-Struktur verwenden. Am Ende des Tages muss eine mit einem Lesezeichen versehene URL für eine bestimmte Ressource etwas enthalten, mit dem Sie eine API-URL abrufen können, die diese Ressource eindeutig identifiziert. Wenn Sie Ihre eigene Kennung generieren und diese mit der API-URL wie in Ansatz 3 zwischenspeichern, funktioniert dies so lange, bis jemand versucht, diese mit Lesezeichen versehene URL zu verwenden, nachdem dieser Eintrag aus dem Cache gelöscht wurde.

Was ist, wenn die Entitäten meiner Web-App nicht den API-Entitäten 1-1 zugeordnet wurden?

Die Antwort hängt von der Beziehung ab. In beiden Fällen benötigen Sie eine Möglichkeit, das Front-End API-URLs zuzuordnen.

5
Mike Partridge

Seien wir ehrlich, es gibt keine magische Lösung. Haben Sie Richardson Maturity Model gelesen? Es unterteilt REST Architekturreife in drei Ebenen: Ressourcen, HTTP-Verben und Hypermedia-Steuerelemente.

Ich sollte keine rohen Bezeichner meiner Entitäten verfügbar machen, sondern Hyperlinks mit rel = "self" zurückgeben.

Dies ist Hypermedia-Kontrollen. Brauchen Sie es wirklich? Dieser Ansatz hat einige sehr gute Vorteile (Sie können darüber lesen hier ). Aber es gibt keine kostenlosen Mahlzeiten und Sie müssen hart arbeiten (z. B. Ihre zweite Lösung), wenn Sie sie erhalten möchten.

Es ist eine Frage des Gleichgewichts - möchten Sie die Leistung opfern (und Ihren Code komplizierter machen), aber ein System erhalten, das flexibler ist? Oder möchten Sie die Dinge lieber schneller und einfacher halten, aber später bezahlen, wenn Sie Änderungen an Ihrer API/Ihrem Modell vornehmen?

Als jemand, der ein ähnliches System entwickelt hat (Business Logic Tier, Web Tier und Web Clients), habe ich mich für die zweite Option entschieden. Da meine Gruppe alle Ebenen entwickelt hat, haben wir beschlossen, dass es besser ist, ein wenig zu koppeln (indem wir die Webschicht über Entitäts-IDs informieren und API-URLs erstellen) und im Gegenzug Code zu erhalten, der einfacher ist. Die Abwärtskompatibilität war in unserem Fall ebenfalls nicht relevant.

Wenn die Webanwendung von einem Drittanbieter entwickelt wurde oder wenn die Abwärtskompatibilität ein Problem darstellte, haben wir möglicherweise eine andere Wahl getroffen, da es von großem Wert war, die URL-Struktur zu ändern, ohne die Webanwendung zu ändern. Genug, um die Komplikation des Codes zu rechtfertigen.

Bedeutet das alles, dass RESTful-APIs nicht als Backend für Webanwendungen dienen können?

Ich denke, es bedeutet, dass Sie keine perfekte Implementierung erstellen müssen REST. Sie können mit Ihrer zweiten Lösung fortfahren oder Entitäts-IDs oder vielleicht API-URLs übergeben offenlegen Es ist in Ordnung, solange Sie die Auswirkungen und Kompromisse verstehen.

2
daramasala

Der einfachste Weg besteht wahrscheinlich darin, nur die API-URLs von Ressourcen als Zeichenfolgenkennungen zu verwenden. Aber Webseiten-URLs wie http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234 sind hässlich.

Ich denke du hast recht, das ist der einfachste Weg. Sie können die URLs gegen http://my.rest.api/api Relativieren, um sie weniger hässlich zu machen:

http://my.web.app/person/person%2F1234

Wenn die von der API bereitgestellte URL nicht relativ zu dieser Basis ist, verschlechtert sie sich in die hässliche Form:

http://my.web.app/person/http%3A%2F%2Fother.api.Host%2Fapi%2Fperson%2F1234

Um noch einen Schritt weiter zu gehen, überprüfen Sie die Antwort vom API-Server, um festzustellen, welche Art von Ansicht Sie anzeigen möchten, und beenden Sie die Codierung des Pfadsegmentbegrenzers und der Doppelpunkte:

http://my.web.app/person/1234 (best case)
http://my.web.app/http://other.api.Host/api/person/1234 (ugly case)
0
ajlane

Ich denke, wenn Sie sich an etwas halten, das dem Atom Syndication Format du bist gut.

Hier können die Metadaten, die den dargestellten Eintrag beschreiben, mithilfe zusätzlicher Elemente/Attribute angegeben werden:

  • Enthält gemäß [RFC4287] einen URI, der den Eintrag eindeutig identifiziert

  • Gemäß [RFC4287] ist dieses Element optional. Wenn enthalten, enthält es den URI, den ein Client zum Abrufen des Eintrags verwenden sollte.

Das sind nur meine zwei Cent.

0
rusev

Sorgen Sie sich nicht um die URLs, sondern um die Medientypen.

Siehe hier (insbesondere dritter Aufzählungspunkt).

Eine REST API sollte fast den gesamten beschreibenden Aufwand für die Definition der Medientypen verwenden, die zur Darstellung von Ressourcen und zur Steuerung des Anwendungsstatus verwendet werden, oder für die Definition erweiterter Beziehungsnamen und/oder hypertextfähiger Markierungen -up für vorhandene Standardmedientypen ...


Im Fall einer typischen Web-App ist der Client ein Mensch ; Der Browser ist nur ein Agent .

Also ein Ankertag wie

          <a href="example.com/foo/123">click here</a>

entspricht so etwas wie

          <link type="text/html" rel="self" href="example.com/foo/123">

Die URL ist für den Benutzer immer noch undurchsichtig. Sie kümmert sich nur um die Medientypen (z. B. text/html, application/pdf, application/flv, video/x-flv, image/jpeg, image/funny-cat-picture etc). Der im Anker (und im title-Attribut) enthaltene beschreibende Text ist nur eine Möglichkeit, den Beziehungstyp auf eine für den Menschen verständliche Weise zu erweitern.

Der Grund, warum der URI für Clients undurchsichtig sein soll, besteht darin, dass Sie die Kopplung reduzieren (eines der Hauptziele von REST). Der Server kann die URIs ändern/neu organisieren, ohne den Client zu beeinflussen (solange Sie über eine gute Caching-Richtlinie verfügen - was möglicherweise überhaupt kein Caching bedeutet).

Zusammenfassend

Stellen Sie einfach sicher, dass sich der Client (Mensch oder Maschine) eher um die Medientypen und die Beziehungen als um die URLs kümmert, und alles wird gut.

0
Rodrick Chapman