1. Einleitung
Die CaaS-Plattform ermöglicht Unternehmen die flexible Bereitstellung und Nutzung von Inhalten über verschiedene digitale Kanäle.
Sie besteht aus der REST-Schnittstelle (caas-rest-api) zur Verwaltung und Abfrage von Inhalten über HTTP sowie dem CaaS-Repository (caas-mongo), der internen Datenbank zur Speicherung der Inhalte.
Dieses Dokument richtet sich an Benutzer der REST-Schnittstelle der CaaS-Plattform und beschreibt deren Funktionen und Nutzungsmöglichkeiten. Hinweise und Anleitungen zum Betrieb und zur technischen Administration der Plattform finden Sie in der separaten Betriebsanleitung.
2. Grundlagen der REST-Schnittstelle
Die REST-Schnittstelle ermöglicht das Verwalten und Abfragen von Inhalten und Medien als JSON-Dokumente über HTTP. Sie unterstützt Authentifizierung und Autorisierung per API-Key oder Sicherheitstoken und liefert Ergebnisse im JSON-Format. Neben CRUD-Operationen auf Dokumenten können auch Datenbanken, Collections, API-Keys und Indizes verwaltet werden. Die Schnittstelle bietet zudem Funktionen wie Pagination, Filterung und das Auflösen von Referenzen. Zusätzlich können Daten flexibel über eigene Aggregationen sowie GraphQL-Endpunkte abgefragt und verwaltet werden.
2.1. Authentifizierung
Jede Anfrage an die REST-Schnittstelle muss authentifiziert werden, ansonsten wird sie abgewiesen. Die verschiedenen Möglichkeiten der Authentifizierung werden nachfolgend erläutert.
2.1.1. Methode API-Key
Anfragen mit API-Key müssen einen HTTP-Header mit Bearer Token enthalten: Authorization: Bearer <key>.
Als Wert von key wird der Wert des Attributs key des verwendeten API-Keys erwartet.
Weitere Informationen finden Sie im Abschnitt Validierung von API-Keys.
2.1.2. Methode Sicherheitstoken
Es ist möglich, zu einem API-Key ein kurzlebiges (bis zu 24 Stunden) Sicherheitstoken zu generieren. Das Token beinhaltet dieselben Berechtigungen wie der API-Key, zu dem es generiert wurde.
Es gibt zwei Möglichkeiten, diese Token zu generieren und zu nutzen:
-
Query Parameter
eine mit API-Key authentifizierte GET-Anfrage auf den Endpunkt/_logic/securetoken?tenant=<database>generiert ein Sicherheitstoken. Solch ein Token kann nur für eine konkrete Datenbank ausgestellt werden, unabhängig davon ob der API-Key Berechtigungen auf mehrere Datenbanken hat. Ein Parameter&ttl=<Lebensdauer in Sekunden>wird unterstützt und ist optional. Das Sicherheitstoken steht in der JSON-Rückgabe.Jede Anfrage an die REST-Schnittstelle kann optional über einen Query-Parameter
?securetoken=<token>authentifiziert werden. -
Cookie
eine mit API-Key authentifizierte GET-Anfrage auf den Endpunkt/_logic/securetokencookie?tenant=<database>generiert ein Sicherheitstoken-Cookie. Solch ein Cookie kann nur für eine konkrete Datenbank ausgestellt werden, unabhängig davon, ob der API-Key Berechtigungen auf mehrere Datenbanken hat. Ein Parameter&ttl=<Lebensdauer in Sekunden>wird unterstützt und ist optional. Die Rückgabe beinhaltet einenSet-Cookie-Header mit dem Sicherheitstoken.Alle Anfragen mit diesem Cookie werden automatisch authentifiziert.
2.2. API-Keys
API-Keys ermöglichen die Authentifizierung und Autorisierung von Anfragen an die REST-Schnittstelle. Sie enthalten eine Liste von Berechtigungen, die definieren, welche Aktionen auf welchen Ressourcen erlaubt sind.
API-Keys können auf zwei Ebenen verwaltet werden: global oder lokal pro Datenbank. Entsprechend gibt es zwei API-Key-Typen, welche sich durch ihren Gültigkeitsbereich voneinander unterscheiden:
-
Globale API-Keys
globale API-Keys sind datenbankübergreifend und werden in der Collectionapikeysder Datenbankcaas_adminverwaltet. Sie ermöglichen es, Berechtigungen für Ressourcen in mehreren oder gar allen Datenbanken zu definieren. -
Lokale API-Keys
lokale API-Keys sind pro Datenbank definiert und werden dementsprechend in der Collectionapikeyseiner beliebigen Datenbank verwaltet. Anders als globale API-Keys können lokale API-Keys nur Berechtigungen für Ressourcen innerhalb derselben Datenbank definieren.
Bei der Authentifizierung mit API-Key durchsucht die CaaS-Plattform immer zunächst die lokalen API-Keys. Wird kein passender API-Key gefunden, so werden danach die globalen API-Keys evaluiert.
2.2.1. Autorisierungsmodell
Die Autorisierung eines API-Keys wird auf Basis jeder Berechtigung ausgeführt, die Teil des API-Keys sind. Die Liste von Berechtigungen werden im Attribut permissions des API-Keys definiert.
Eine Berechtigung besitzt die folgenden Attribute:
-
url: gibt den Pfad an, auf den sich die Berechtigung bezieht (z.B. eine Collection oder ein Endpunkt) -
permissionMode: bestimmt die Art der Prüfung, z.B. PREFIX, REGEX oder GRAPHQL -
methods: listet die erlaubten HTTP-Methoden auf (z.B. GET, POST, PUT)
Bei der Prüfung einer Berechtigung wird das Attribut url herangezogen. Dessen Wert wird gegen den URL-Pfad eines eingehenden Requests geprüft. Die Art der Prüfung ist abhängig vom permissionMode der Berechtigung.
Es gibt drei verschiedene Berechtigungsmodi:
-
PREFIXundREGEX
Im ModusPREFIXwird geprüft, ob der Wert desurlAttributs ein Präfix des URL-Pfades eines eingehenden Requests ist.Im Modus
REGEXmuss ein regulärer Ausdruck imurlAttribut hinterlegt werden. Die Prüfung erfolgt dann durch den Abgleich, ob der URL-Pfad eines eingehenden Requests dem Muster des regulären Ausdrucks entspricht.Darüber hinaus existiert für die Berechtigungsmodi
PREFIXundREGEXeine grundlegende Unterscheidung zwischen der Funktionsweise von globalen und lokalen API-Keys. Globale API-Keys prüfen immer gegen den gesamten Pfad des Requests, lokale API-Keys hingegen gegen den Teil des Pfads nach der Datenbank. Weitere Informationen zu globalen und lokalen API-Keys können dem Beispiel Unterscheidung lokaler und globaler API-Key oder dem Kapitel API-Keys entnommen werden. -
GRAPHQL
Der ModusGRAPHQLerlaubt die Berechtigung zur Ausführung einer GraphQL-Applikation. Dabei wird der Wert desurlAttributs mit der URI einer GraphQL-Applikation verglichen, die ein eingehender Request benutzt. Die URI einer GraphQL-Applikation wird im Attributdescriptor.urider App-Definition angegeben. Weitere Details sind im Kapitel GraphQL zu finden.
Die folgende Tabelle zeigt beispielhaft den Unterschied bei der Autorisierung zwischen lokalen oder globalen API-Keys bei Verwendung des Berechtigungsmodus PREFIX oder REGEX.
Berechtigung im API-Key (Attribut url) |
Typ des API-Keys | Request URL-Pfad | Zugriff erlaubt |
|---|---|---|---|
|
/ |
global |
/ |
ja |
|
/project/ |
ja |
||
|
/project/content/ |
ja |
||
|
/other-project/ |
ja |
||
|
/other-project/content/ |
ja |
||
|
/project/ |
global |
/ |
nein |
|
/project/ |
ja |
||
|
/project/content/ |
ja |
||
|
/other-project/ |
nein |
||
|
/other-project/content/ |
nein |
||
|
/ |
lokal in |
/ |
nein |
|
/project/ |
ja |
||
|
/project/content/ |
ja |
||
|
/other-project/ |
nein |
||
|
/other-project/content/ |
nein |
||
|
/content/ |
lokal in |
/ |
nein |
|
/project/ |
nein |
||
|
/project/content/ |
ja |
||
|
/other-project/ |
nein |
||
|
/other-project/content/ |
nein |
2.2.2. Verwaltung über REST-Endpunkte
Die folgenden Endpunkte stehen für die Verwaltung von API-Keys zur Verfügung:
-
GET /<database>/apikeys
-
POST /<database>/apikeys
zu beachten: die Parameter_idundkeymüssen übergeben werden und identische Werte besitzen -
PUT /<database>/apikeys/{id}
zu beachten: der Parameterkeymuss denselben Wert haben wie die {id} in der URL -
DELETE /<database>/apikeys/{id}
Die zu verwendende Datenbank richtet sich nach dem Typ des API-Keys, siehe Kapitel API-Keys.
|
Zur Verwaltung von API-Keys kann auch ein API-Key als Autorisierungsmethode eingesetzt werden. In dem Fall muss der verwendete API-Key Schreibrechte auf der entsprechenden API-Keys-Collection besitzen. Dies gilt insbesondere auch bei nur lesenden Anfragen und dient dazu, eine Rechteausweitung zu verhindern. |
Beispiel für die Anlage eines lokalen API-Keys mittels curl:
curl "https://REST-HOST:PORT/<tenant>/apikeys" \
-H 'Content-Type: application/json' \
-u '<USER>:<PASSWORD>' \
-d $'{
"_id": "1e0909b7-c943-45a5-ae96-79f294249d48",
"key": "1e0909b7-c943-45a5-ae96-79f294249d48",
"name": "New-Apikey",
"description": "Some descriptive text",
"permissions": [
{
"url": "/<collection>",
"permissionMode": "PREFIX",
"methods": [
"GET",
"PUT",
"POST",
"PATCH",
"DELETE",
"HEAD",
"OPTIONS"
]
}
]
}'
Der in diesem Beispiel gezeigte API-Key ist vom Typ "lokal", da er in der apikeys Collection unterhalb der Datenbank <tenant> liegt und damit lokal für diese Datenbank definiert ist. Die Berechtigung gilt für alle Pfade, die mit /<tenant>/<collection> beginnen, da der Berechtigungsmodus PREFIX verwendet wird, und umfasst alle in methods genannten HTTP-Methoden.
|
Um einen API-Key mit dem Modus REGEX zu erstellen, muss das obige Beispiel wie folgt angepasst werden:
|
|
Die |
2.2.3. Validierung von API-Keys
Jeder API-Key wird bei Anlage und Aktualisierung gegen ein hinterlegtes JSON-Schema validiert. Das JSON-Schema sichert die grundlegende Struktur von API-Keys ab und kann unter /<database>/_schemas/apikeys abgefragt werden.
Weitere Validierungen stellen sicher, dass keine zwei API-Keys mit demselben key angelegt werden können. Ebenso darf ein API-Key eine URL nicht mehrfach enthalten.
Genügt ein API-Key den Anforderungen nicht, so wird der entsprechende Request mit HTTP-Status 400 abgewiesen.
Sollte das JSON-Schema zuvor nicht erfolgreich in der Datenbank hinterlegt worden sein, so werden Requests mit HTTP-Status 500 beantwortet.
|
Das |
2.3. Push-Benachrichtigungen (Change Streams)
Es ist oft gewünscht, über Änderungen in der CaaS-Plattform informiert zu werden. Hierzu bietet die CaaS-Plattform Change Streams. Dieses Feature ermöglicht es eine Websocket-Verbindung zur CaaS-Plattform aufzubauen, worüber Events zu den verschiedenen Änderungen publiziert werden.
Change Streams werden angelegt, indem eine Definition in den Metadaten einer Collection abgelegt wird. Falls Sie CaaS Connect nutzen, so werden für Sie bereits einige vordefinierte Change Streams erstellt. Sie haben auch die Möglichkeit eigene Change Streams zu definieren.
Das Format der Events entspricht den Standard MongoDB Events.
|
Wir empfehlen bei der Arbeit mit Websockets möglicherweise auftretende Verbindungsabbrüche zu berücksichtigen. Regelmäßige |
|
Sie finden ein Beispiel für die Nutzung von Change Streams im Browser im Appendix. |
2.4. Zusätzliche Informationen
Weitere Informationen über die Funktionalität der REST-Schnittstelle finden Sie in der offiziellen RESTHeart-Dokumentation.
3. REST-API
3.1. Abfragen von Dokumenten und Medien
Inhalte werden in sogenannten Collections abgelegt, die Datenbanken unterstellt sind. Es gilt dabei das folgende dreiteilige URL-Schema:
https://REST-HOST:PORT/<database>/<collection>/<document>
Abfragen erfolgen über die HTTP-Methode GET.
Für binäre Inhalte sind besondere Collections (sogenannten Buckets) vorgesehen, welche immer mit dem Suffix .files enden. Das Ergebnisdokument enthält im Falle eines Mediums nicht die Binärdaten, sondern Links, welche auf die URL mit den eigentlichen Binärdaten verweisen. Weitere Informationen zu binären Inhalten entnehmen Sie bitte der RESTHeart-Dokumentation.
|
Bitte beachten Sie, dass binäre Inhalte bei unserem SaaS-Angebot nicht in die CaaS-Buckets übertragen werden. |
Bei Einsatz von CaaS Connect finden Sie in der CaaS Connect-Dokumentation weitere Informationen.
3.1.1. Einsatz von Filtern
Filter kommen immer dann zum Einsatz, wenn Dokumente nicht über ihre Id, sondern über deren Inhalt ermittelt werden sollen. Auf diesem Weg lassen sich sowohl einzelne als auch mehrere Dokumente abrufen.
Die Abfrage aller englischsprachiger Dokumente aus der Collection products besitzt beispielsweise folgenden Aufbau:
https://REST-HOST:PORT/<database>/products?filter={fs_language:"EN"}
|
Über dieses Beispiel hinaus existieren weitere Filtermöglichkeiten. Weitere Informationen hierzu finden Sie in der Query-Dokumentation. |
|
Bitte beachten Sie, dass der Query-Parameter |
3.1.2. Format der Ergebnisdokumente
Die Schnittstelle liefert im Standard alle JSON-Daten im HAL-Format zurück. Es handelt sich bei ihnen somit nicht um schlichte Rohdaten, wie zum Beispiel traditionell unstrukturierte Inhalte im JSON-Format.
Das HAL-Format bietet den Vorteil einer einfachen, aber mächtigen Strukturierung. Neben den geforderten Inhalten enthalten die Ergebnisse zusätzliche Meta-Informationen zur Struktur dieser Inhalte.
Beispiel
{ "_size": 5,
"_total_pages": 1,
"_returned": 3,
"_embedded": { CONTENT }
}
In diesem Beispiel wurde eine gefilterte Abfrage abgesetzt. Ohne die genauen Inhalte zu kennen, ist ihre Struktur aufgrund der Meta-Informationen direkt ablesbar. Die REST-Schnittstelle liefert an dieser Stelle aus einer Menge von fünf Dokumenten drei den Filterkriterien entsprechende Ergebnisse zurück und stellt diese auf einer einzigen Seite dar.
|
Handelt es sich bei einem angefragten Element um ein Medium, ermittelt die URL lediglich dessen Metadaten. |
3.1.3. Seitengröße der Abfragen
Die Ergebnisse der REST-Schnittstelle werden immer paginiert ausgeliefert, um Performance-Probleme bei großen Collections zu vermeiden. Zur Steuerung der angefragten Seite und der Anzahl von Dokumenten pro Seite können bei GET-Anfragen die HTTP-Query-Parameter page und pagesize verwendet werden.
Der Standardwert für den pagesize-Parameter ist in der CaaS-Plattform auf 20 gesetzt und das Maximum auf 100.
Diese Werte können im Falle einer On-Premises-Installation geändert werden (siehe Betriebsanleitung).
Weitere Informationen finden Sie in der RESTHeart-Dokumentation.
3.1.4. Auflösen von Referenzen
CaaS-Dokumente können andere CaaS-Dokumente referenzieren. Bei der Verarbeitung von Dokumenten werden die referenzierten Inhalte häufig direkt benötigt. Um sequentielle Abfragen in diesen Fällen zu umgehen, kann der Query Parameter resolveRef verwendet werden.
Die folgenden zwei JSON-Dokumente zeigen dies beispielhaft:
{
"_id": "my-document",
"fsType": "ProjectProperties",
"formData": {
"ps_audio": {
"fsType": "FS_REFERENCE",
"value": {
"fsType": "PageRef",
"url": "https://REST-HOST:PORT/my-db/col/my-referenced-document"
}
}
}
}
{
"_id": "my-referenced-document",
"fsType": "PageRef",
"name": "audio"
}
Im ersten Dokument steht im JSON unter formData.ps_audio.value.url eine absolute URL auf ein anderes Dokument im CaaS. Folgender Request zeigt beispielhaft, wie diese Referenz im gleichen Request aufgelöst wird, der das Dokument ausliest.
curl -X GET --location "https://REST-HOST:PORT/my-db/col/my-document?resolveRef=formData.ps_audio.value.url" \
-H "Authorization: Bearer my-api-key"
Als Wert des Query-Parameters muss dabei der im JSON genannte URL-Pfad angeben werden. Die Antwort enthält dann ein zusätzliches Attribut _resolvedRefs:
{
"_id": "my-document",
"fsType": "ProjectProperties",
"formData": {
"ps_audio": {
"fsType": "FS_REFERENCE",
"value": {
"fsType": "PageRef",
"url": "https://REST-HOST:PORT/my-db/col/my-referenced-document"
}
}
},
"_resolvedRefs": {
"https://REST-HOST:PORT/my-db/col/my-referenced-document": {
"_id": "my-referenced-document",
"fsType": "PageRef",
"name": "audio"
}
}
}
|
Die Auflösung von Referenzen wird beeinflusst durch die Konfiguration und Einschränkungen. |
Der Parameter resolveRef wird auch für Collection-Anfragen unterstützt. In diesem Fall werden die Referenzen in allen zurückgegebenen Dokumenten aufgelöst. Die Dokumente der aufgelösten Referenzen werden dabei in einem neuen, zusätzlichen Dokument gesammelt, welches wiederum zum Array der Antwort hinzugefügt wird.
curl -X GET --location "https://REST-HOST:PORT/my-db/col?resolveRef=formData.ps_audio.value.url" \
-H "Authorization: Bearer my-api-key"
[
{
"_id": "my-document",
"fsType": "ProjectProperties",
"formData": {
"ps_audio": {
"fsType": "FS_REFERENCE",
"value": {
"fsType": "PageRef",
"url": "https://REST-HOST:PORT/my-db/col/my-referenced-document"
}
}
}
},
{
"_id": "_resolvedRefs",
"https://REST-HOST:PORT/my-db/col/my-referenced-document": {
"_id": "my-referenced-document",
"fsType": "PageRef",
"name": "audio"
}
}
]
|
Dieses zusätzliche Dokument ist immer das letzte Element im Array der Antwort und kann durch die ID |
|
Der Query-Parameter |
Transitive Referenzen
Möglicherweise enthalten referenzierte Dokumente ihrerseits weitere Referenzen. Auch diese können im ursprünglichen Request aufgelöst werden. Dafür muss der Pfad zur nächsten Referenz ebenfalls in der Anfrage angegeben werden, inklusive des Prefixes $i., wobei i die Tiefe der Referenzauflösungskette beschreibt.
Folgender Request zeigt dies bezogen auf das vorherige Beispiel, anhand einer Referenz in dem Attribut page.url des Dokumentes my-referenced-document:
curl -X GET --location "https://REST-HOST:PORT/my-db/col?resolveRef=formData.ps_audio.value.url&resolveRef=$1.page.url" \
-H "Authorization: Bearer my-api-key"
Referenzpfad Syntax
Tiefe 0 beschreibt die Dokumente, die der ursprüngliche Request in der Antwort bereits enthalten wird. Für die Tiefe 0 ist der Prefix $0. optional. Tiefe 1+ beschreibt alle Dokumente, die durch erfolgreiches Auflösen der Referenzen auf der jeweils vorherigen Tiefe gefunden wurden.
| Tiefe | JSON Dokument | resolveRef | Erklärung |
|---|---|---|---|
|
0 |
|
|
In allen Dokumenten der Tiefe 0 wird unter dem Pfad |
|
|
|||
|
|
In allen Dokumenten der Tiefe 0 wird das Array mit dem Namen |
|
|
|
Nur im ersten Objekt des Arrays wird |
||
|
|
Nur im zweiten Objekt des Arrays wird |
||
|
|
Es werden alle Arrays im |
|
|
|
Es wird das erste Array im |
||
|
1 |
<JSON Dokument> |
|
Die Pfade müssen mit |
|
n |
<JSON Dokument> |
|
Die Pfade müssen mit |
Konfiguration und Einschränkungen
-
Es können nur absolute URLs aufgelöst werden.
-
Es werden beim Auflösen der Referenzen keine Fehler geworfen, falls inkorrekte Pfade oder URLs angegeben werden. Inkorrekte Pfade und Referenzen werden still ignoriert.
-
Pfade müssen gemäß der Referenzpfad Syntax angegeben werden. Die Syntax orientiert sich an JsonPath, unterstützt werden aber nur genau die dokumentierten Operatoren.
-
Die URLs werden in dem
_resolvedRefsDokument nicht normalisiert. URL-Referenzen, die nicht exakt identisch sind, werden als unterschiedliche Dokumente gewertet, auch wenn sie auf dasselbe Dokument im CaaS zeigen. Dies kann z. B. durch ein zusätzliches/am Ende der URL oder durch unterschiedliche Query-Parameter ausgelöst werden. -
Standardmäßig ist die maximale Tiefe der Referenzauflösung 3. Somit kann maximal
$2.als Pfad-Präfix für Referenzen benutzt werden. -
Es können in einem Request maximal 100 unterschiedliche Referenzen aufgelöst werden. Sobald dieses Limit erreicht ist, werden keine weiteren Referenzen gesammelt und damit auch nicht Teil der Response sein.
-
Die Referenzauflösung ist standardmäßig aktiviert.
-
Die Einstellungen zu maximaler Tiefe und Limit der Referenzen sowie die Referenzauflösung selbst können in einer On-Premises-Installation geändert werden, siehe Betriebsanleitung.
3.1.5. Indizes für eine effiziente Abfrageausführung
Die Laufzeit von Abfragen mit Filtern (Details siehe Kapitel Einsatz von Filtern) kann sich bei steigender Anzahl an Dokumenten in einer Collection vergrößern. Übersteigt sie einen bestimmten Wert, so wird die Abfrage von der REST-Schnittstelle mit HTTP-Status 408 beantwortet. Eine effizientere Ausführung lässt sich erreichen, indem auf den Attributen, die in den betroffenen Filterabfragen verwendet werden, ein Index erstellt wird.
Detaillierte Informationen zu Datenbank-Indizes entnehmen Sie bitte der Dokumentation der MongoDB.
- Vordefinierte Indizes
-
Falls Sie CaaS Connect im Einsatz haben, werden bereits vordefinierte Indizes erstellt, die einige häufig vorkommende Filterabfragen unterstützen.
Die genauen Definitionen können unter https:/REST-HOST:PORT/<database>/<collection>/_indexes/ abgerufen werden.
- Kundenindividuelle Indizes
-
Sollten die vordefinierten Indizes Ihre Anwendungsfälle nicht abdecken und Sie bei Abfragen lange Antwortzeiten bis hin zu Request Timeouts beobachten, so können Sie eigene Indizes erstellen. Zum Management der gewünschten Indizes kann die REST-Schnittstelle genutzt werden. Die Vorgehensweise ist in der RESTHeart-Dokumentation beschrieben.
|
Bitte legen Sie nur die Indexe an, die Sie benötigen. |
3.2. Ändern und Löschen von Dokumenten
Zur Anpassung von Dokumenten können die HTTP-Methoden POST, PUT und PATCH benutzt werden. Dokumente können darüber hinaus mit dem Verb DELETE gelöscht werden.
Der folgende Ausschnitt zeigt das Anlegen eines Dokumentes my-document innerhalb der Collection my-collection, die sich in der Datenbank my-db befindet.
curl --location --request PUT 'https://REST-HOST:PORT/my-db/my-collection/my-document' \
--header 'Authorization: Bearer my-api-key' \
--header 'Content-Type: application/json' \
--data-raw '{
"data": "some-data"
}'
Weitere Informationen zur Speicherung von Dokumenten können den entsprechenden Abschnitten in der RESTHeart- Dokumentation entnommen werden.
|
Bei der Speicherung von Dokumenten mittels der Verben POST, PUT oder PATCH wird abweichend zu RESTHeart als default der Write Mode |
3.3. Verwalten von Datenbanken und Collections
Im Gegensatz zur Speicherung von Dokumenten ist die Verwaltung von Datenbanken und Collections lediglich auf die HTTP-Methoden PUT und DELETE beschränkt.
Folgender Ausschnitt zeigt das Anlegen der Datenbank my-db mit einem PUT-Request.
curl --location --request PUT 'https://REST-HOST:PORT/my-db' \
--header 'Authorization: Bearer my-api-key'
|
Es gibt reservierte Datenbanken, die nicht zur Speicherung normaler Inhalte genutzt werden können. Zu diesen zählen |
Weitere Informationen zur Verwaltung von Datenbanken können den entsprechenden Abschnitten in der RESTHeart-Dokumentation entnommen werden.
|
Das Verwalten von Datenbanken ist unserem SaaS-Angebot aufgrund von eingeschränkter Zugriffsberechtigung nicht unterstützt. |
Eine Collection my-collection kann wie folgt in der Datenbank my-db mit einem PUT-Request angelegt werden.
curl --location --request PUT 'https://REST-HOST:PORT/my-db/my-collection' \
--header 'Authorization: Bearer my-api-key'
|
Es gibt reservierte Collections, die nicht zur Speicherung normaler Inhalte genutzt werden können. Zu den reservierten Collectionnamen zählen |
Weitere Informationen zur Verwaltung von Collections können den entsprechenden Abschnitten in der RESTHeart-Dokumentation entnommen werden.
4. GraphQL
Im Gegensatz zu klassischen REST-Abfragen bietet GraphQL eine flexible und typisierte Schnittstelle, die komplexe, verschachtelte Datenstrukturen in einer einzigen Anfrage abrufen kann. Dies erleichtert die Entwicklung von Frontends, da weniger Roundtrips und individuelle Endpunkte nötig sind. Zudem ermöglicht GraphQL eine klare Definition des Datenmodells und eine bessere Dokumentation der verfügbaren Abfragen.
|
Mutations werden derzeit nicht unterstützt. |
4.1. Authentifizierung und Autorisierung
Der Authentifizierungs- und Autorisierungsprozess für GraphQL-Abfragen funktioniert anders als bei REST-API-Abfragen. Anders als bei REST-API-Abfragen, bei denen der Request Path der Abfrage gegen eine Liste von erlaubten URLs geprüft wird, werden GraphQL-Abfragen mit einer der folgenden Zugriffschecks autorisiert:
-
Explizite Ausführungserlaubnis
prüft, ob der API-Key eine explizite Erlaubnis hat (GRAPHQLBerechtigung des API-Keys), Abfragen an die GraphQL-Applikation zu senden. -
Implizite Ausführungserlaubnis
prüft, ob der API-Key Zugriff zu allen Datenbanken und Collections hat. Dies wird geprüft, indem die URL Berechtigungen (PREFIXundREGEX) des API-Keys mit den Pfaden aller Datenbanken und Collections abgeglichen werden, auf die die GraphQL-Applikation den Zugriff ermöglicht.
|
Für lokale API-Keys gilt zusätzlich die Bedingung, dass diese nur auf GraphQL-Applikationen der gleichen Datenbank zugreifen dürfen. |
Weitere Informationen zu den verschiedenen Arten von Berechtigungen eines API-Keys können dem Kapitel Autorisierungsmodell entnommen werden.
4.2. Verwalten von GraphQL-Applikationen
Mit der REST-Schnittstelle ist es möglich, eigene GraphQL-Applikationen zu erstellen, zu aktualisieren und zu löschen. Falls Sie CaaS Connect im Einsatz haben, werden bereits vordefinierte Applikationen erstellt, die speziell auf die Abfrage von FirstSpirit-Inhalten zugeschnitten sind.
Eine GraphQL-Applikation besitzt eine App-Definition, welche in der Collection gql-apps abzulegen ist. Diese Collection wird automatisch bei der Anlage/Aktualisierung einer Datenbank erzeugt. Sollte sie jedoch trotzdem noch nicht in der Datenbank existieren, so muss sie zuvor manuell mit einem PUT-Request angelegt werden.
|
Die |
Beim Bearbeiten der GraphQL-App-Definition (z.B. Erstellen/Aktualisieren einer Applikation) werden die Berechtigungen des API-Key überprüft. Eine Operation kann nur durchgeführt werden, wenn der API-Key Zugriff auf alle in der Definition aufgeführten Datenbanken und Collections hat.
|
Eine Kurzanleitung, die als Einstieg dient, ist im Anhang unter Quickstart: GraphQL-Applikationen zu finden. |
4.2.1. Erstellen/Aktualisieren einer Applikation
Um eine GraphQL-Applikation zu erstellen oder zu aktualisieren, wird eine PUT-Anfrage mit der App-Definition an die folgende URL gestellt:
https://REST-HOST:PORT/<tenant>/gql-apps/<app-uri>
Dabei gilt:
-
<app-uri> muss den Wert <tenant>___<my-appname> besitzen.
-
der Parameter
descriptor.urider App-Definition muss mit <app-uri> übereinstimmen und ist im CaaS - abweichend von den Angaben in der RESTHeart-Dokumentation - nicht optional.
Dadurch wird ein Endpunkt unter der URL https://REST-HOST:PORT/graphql/<app-uri> provisioniert, an den dann GraphQL-Abfragen gerichtet werden können. Informationen über die Ausführung von GraphQL-Abfragen befinden sich im Kapitel GraphQL-API.
Alle Operationen an GraphQL-Applikationen werden aus technischen Gründen im Hintergrund automatisch in die Collection /caas_admin/gql-apps gespiegelt. Das Kapitel Re-Synchronisierung der vorhandenen GraphQL-Applikationen enthält Informationen, wie dieser Mechanismus bei Bedarf auch manuell ausgeführt werden kann.
Angabe der App-Definition
Zur Angabe der App-Definition in der PUT-Anfrage bestehen zwei Möglichkeiten:
-
Verwendung des JSON-Body
die komplette App-Definition wird im Request-Body (Content-Typeapplication/json) übergeben.Ein Beispiel für eine solche GraphQL-App-Definition ist im Kapitel GraphQL Beispiel-Applikation zu finden.
-
Verwendung des Datei-Uploads
statt die gesamte App-Definition zu senden, kann die Definition auch als Multipart-Upload (Content-Typemultipart/form-data) übertragen werden.
Dabei werden die Bestandteile der App-Definition in zwei separate Dateien aufgeteilt, welche als einzelne Dateiparts im Request übermittelt werden müssen:
Teilapp: Datei mit Bereichendescriptorundmappingim JSON-Format.
Teilschema: Datei mit der Rohtextversion vonschemain der Schemadefinitionssprache GraphQL.Hochladen der Dateien mittelscurlcurl -i -X PUT \ -H "Authorization: Bearer $API_KEY" \ -F app=@my-app-def.json \ -F schema=@my-schema.gql \ https://REST-HOST:PORT/<tenant>/gql-apps/<tenant>___<name>Für schnelle Feedback-Zyklen während der Entwicklung kann dies mit einem Tool zur Überwachung von Datei-Änderungen kombiniert werden, um die GraphQL-Applikation kontinuierlich zu aktualisieren:
Kontinuierliches Hochladen der Dateien mittelsfswatchundcurlfswatch -o my-app-def.json my-schema.gql | xargs -n1 -I{} \ curl -i -X PUT \ -H "Authorization: Bearer $API_KEY" \ -F app=@my-app-def.json \ -F schema=@my-schema.gql \ https://REST-HOST:PORT/<tenant>/gql-apps/<tenant>___<name>
Hinweise
-
Eine GraphQL-Applikation kann die Daten mittels einer MongoDB-Query oder -Aggregation abfragen. Das Kapitel Object Mappings der RESTHeart-Dokumentation enthält genauere Informationen. Ein Beispiel einer GraphQL-Applikation, die eine Aggregation nutzt, ist im Anhang zu finden.
Variablen innerhalb von berechtigungsrelevanten Attributen von Aggregation-Stages (wie z.B. Datenbank- oder Collection-Namen) sind nicht erlaubt.
-
Bei komplexen Mappings mit mehreren Fremdschlüsselbeziehungen kann es bei Abfragen zu erhöhten Antwortzeiten kommen. Für eine effizientere Abfrageausführung empfehlen wir die Verwendung von Indizes. Auch die Konfiguration von Batching und Caching kann bei der Optimierung von Antwortzeiten helfen. Details dazu finden Sie in dieser Dokumentation.
4.2.2. Löschen der Applikation
Um eine GraphQL-Applikationen zu löschen, wird eine DELETE-Anfrage an die folgende URL gestellt:
https://REST-HOST:PORT/<tenant>/gql-apps/<tenant>___<name>
4.2.3. Re-Synchronisierung der vorhandenen GraphQL-Applikationen
Unter bestimmten Bedingungen, wie zum Beispiel nach der Wiederherstellung einzelner Collections aus einem Backup, kann es vorkommen, dass die zuvor erstellten GraphQL-Applikationen nicht mehr synchronisiert sind. In so einem Fall müssen alle Tenant-spezifischen GraphQL-Applikationen neu synchronisiert werden.
Um alle vorhandenen GraphQL-Applikationen aller Tenants neu zu synchronisieren, ist eine POST-Anfrage gegen den HTTP-Endpunkt /_logic/sync-gql-apps auszuführen.
4.3. GraphQL-API
Jede der über die Management-API definierten GraphQL-Applikationen (siehe GraphQL) stellt einen GraphQL API-Endpunkt bereit. Dieser Endpunkt kann zum Abrufen von Daten verwendet werden (siehe Daten abrufen).
4.3.1. Daten abrufen
Die GraphQL-API kann über folgende HTTP-Endpunkte abgefragt werden:
https://REST-HOST:PORT/graphql/<app-uri>
Um Daten abzufragen, senden Sie einen POST-Request an den gewünschten Endpunkt und geben die Abfrage mit JSON im Request Body an, z. B.:
curl
curl -i -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{"query": "query($lang: [String!]){products(_language: $lang) {name description categories {name} picture {name binaryUrl width height}}}", "variables": {"lang": ["EN"]}}' \
https://REST-HOST:PORT/graphql/<app-uri>
|
Ein ausführlicheres Beispiel für die Verwendung von GraphQL finden Sie im Anhang. |
|
Analog zu Seitengrößen Limits für REST-Abfragen existiert auch für GraphQL-Abfragen eine Beschränkung der Ergebnismenge. Der Standardwert beträgt 20 Dokumente. Bitte nutzen Sie Pagination-Argumente, sofern mehr Dokumente abgefragt werden müssen. Weitere Informationen können dem Bereich |
4.3.2. Model Context Protocol (MCP) Server für KI (Alpha)
Wir bieten einen experimentellen MCP-Server, der KI-Agenten dabei unterstützt, besser mit der FirstSpirit GraphQL-API zu interagieren. Er hilft der KI dabei, gültige GraphQL-Abfragen zu erstellen und deren Funktionsfähigkeit zu überprüfen. Weitere Informationen finden Sie in der Dokumentation zum CaaS MCP-Server sowie in der Dokumentation zur FirstSpirit GraphQL-API.
5. Appendix
5.1. Beispiele
5.1.1. Nutzen eines Change Streams
<script type="module">
import PersistentWebSocket from 'https://cdn.jsdelivr.net/npm/pws@5/dist/index.esm.min.js';
// Replace this with your API key (needs read access for the preview collection)
const apiKey = "your-api-key";
// Replace this with your preview collection url (if not known copy from CaaS Connect Project App)
// e.g. "https://REST-HOST:PORT/my-tenant-id/f948bb48-4f6b-4a8a-b521-338c9d352f2b.preview.content"
const previewCollectionUrl = new URL("your-preview-collection-url");
const pathSegments = previewCollectionUrl.pathname.split("/");
if (pathSegments.length !== 3) {
throw new Error(`The format of the provided url '${previewCollectionUrl}' is incorrect and should only contain two path segments`);
}
(async function(){
// Retrieving temporary auth token
const token = await fetch(new URL(`_logic/securetoken?tenant=${pathSegments[1]}`, previewCollectionUrl.origin).href, {
headers: {'Authorization': `Bearer ${apiKey}`}
}).then((response) => response.json()).then((token) => token.securetoken).catch(console.error);
// Establishing WebSocket connection to the change stream "crud"
// ("crud" is the default change stream that the CaaS Connect module provides)
const wsUrl = `wss://${previewCollectionUrl.host + previewCollectionUrl.pathname}`
+ `/_streams/crud?securetoken=${token}`;
const pws = new PersistentWebSocket(wsUrl, { pingTimeout: 60000 });
// Handling change events
pws.onmessage = event => {
const {
documentKey: {_id: documentId},
operationType: changeType,
} = JSON.parse(event.data);
console.log(`Received event for '${documentId}' with change type '${changeType}'`);
}
})();
</script>
5.1.2. GraphQL Beispiel-Applikation
In diesem Kapitel wird ein Anwendungsfall für eine GraphQL-Applikation exemplarisch beschrieben. Dazu werden die einzelnen Schritte skizziert, die zum Anlegen einer GraphQL-Applikation und deren späteren Nutzung gehören.
Anlegen der GraphQL-App-Definition
In dem Beispielszenario wird eine GraphQL-Applikation angelegt, mit der man im CaaS liegende Datensätze abfragen kann. Als Datensätze werden hier die Produkte aus dem Beispielprojekt der fiktiven Firma “Smart Living” verwendet. In den Datensätzen befindliche Bildreferenzen und Produktkategorien werden dabei direkt aufgelöst.
Der gesamte Aufruf zur Erstellung der GraphQL-App-Definition für dieses Beispielszenario sieht wie folgt aus.
curl --location --request PUT 'https://REST-HOST:PORT/mycorp-dev/gql-apps/mycorp-dev___products' \
--header 'Authorization: Bearer <PERMITTED_APIKEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"descriptor": {
"name": "products",
"description": "example app to fetch product relevant information from SLG",
"enabled": true,
"uri": "mycorp-dev___products"
},
"schema": "type Picture{ name: String! identifier: String! binaryUrl: String! width: Int! height: Int! } type Category{ name: String! identifier: String! } type Product{ name: String! identifier: String! description: String categories: [Category] picture: Picture } type Query{ products(_language: [String!] = [\"DE\", \"EN\"]): [Product] }",
"mappings": {
"Category": {
"name": "displayName",
"identifier": "_id"
},
"Picture": {
"name": "displayName",
"identifier": "_id",
"binaryUrl": "resolutionsMetaData.ORIGINAL.url",
"width": "resolutionsMetaData.ORIGINAL.width",
"height": "resolutionsMetaData.ORIGINAL.height"
},
"Product": {
"name": "displayName",
"identifier": "_id",
"description": "formData.tt_abstract.value",
"picture": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"identifier": {
"$fk": "formData.tt_media.value.0.formData.st_media.value.identifier"
},
"locale.identifier": {
"$fk": "locale.identifier"
}
}
},
"categories": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"identifier": {
"$in": {
"$fk": "formData.tt_categories.value.identifier"
}
},
"locale.identifier": {
"$fk": "locale.identifier"
}
}
}
},
"Query": {
"products": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"locale.identifier": { "$in": { "$arg": "_language" } },
"entityType": "product"
}
}
}
}
}'
|
Bei der Erstellung einer GraphQL-App-Definition muss das Schema als JSON-String angegeben werden. Zur besseren Lesbarkeit empfehlen wir eine geeignetere Formatierung des Schemas. |
Schema der GraphQL-App-Definition
Das Schema, welches für das Beispiel verwendet wird, enthält folgende Definitionen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type Picture {
name: String!
identifier: String!
binaryUrl: String!
width: Int!
height: Int!
}
type Category {
name: String!
identifier: String!
}
type Product {
name: String!
identifier: String!
description: String
categories: [Category]
picture: Picture
}
type Query {
products(_language: [String!] = ["DE", "EN"]): [Product]
}
In den Zeilen 1, 9 und 14 des Schemas beginnen die Typdefinitionen der Objekte, die in der GraphQL-Applikation verwendet werden. Zudem enthält jedes GraphQL-Schema einen Query Type (Zeile 22), in dem definiert wird, welche Daten von einer GraphQL-Applikation abgefragt werden können. Mehr Details zu Schemas in GraphQL können der GraphQL-Dokumentation entnommen werden.
In diesem Beispiel werden wir Produktdatensätze abfragen. Das wird in Zeile 23 des Schemas durch den Typen [Product] ermöglicht. Bei den Abfragen sollen die Sprachen angegeben werden können, für die wir Produkte erhalten wollen. Die Angabe der Sprache soll in diesem Beispiel optional sein. Diese Anforderung wird durch die Angabe einer Variablen mit dem Namen _language ermöglicht, die mit dem Standardwert ["DE", "EN"] vorbelegt ist.
Mapping der GraphQL-App-Definition
Das Mapping der GraphQL-App-Definition stellt die Verbindung zwischen dem Schema und den Daten in der Datenbank dar. Jeder Type, welcher im Schema beschrieben ist, benötigt im Allgemeinen einen expliziten Eintrag, daher ist dieser Teil einer GraphQL-App-Definition meist der längste. Es kann Situation geben, in denen die Felder im Type exakt so heißen sollen, wie die Schlüssel der Daten. In diesem Spezialfall ist kein expliziter Eintrag im Mapping notwendig. Details zu dem Mapping in GraphQL-App-Definition finden Sie in dem entsprechenden Kapitel in der RESTHeart-Dokumentation.
Das folgende Beispiel ist ein Auszug aus dem Anlegen einer GraphQL-App-Definition und klärt einige Anwendungsfälle auf.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
{
"Category": {
"name": "displayName",
"identifier": "_id"
},
"Picture": {
"name": "displayName",
"identifier": "_id",
"binaryUrl": "resolutionsMetaData.ORIGINAL.url",
"width": "resolutionsMetaData.ORIGINAL.width",
"height": "resolutionsMetaData.ORIGINAL.height"
},
"Product": {
"name": "displayName",
"identifier": "_id",
"description": "formData.tt_abstract.value",
"picture": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"identifier": {
"$fk": "formData.tt_media.value.0.formData.st_media.value.identifier"
},
"locale.identifier": {
"$fk": "locale.identifier"
}
}
},
"categories": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"identifier": {
"$in": {
"$fk": "formData.tt_categories.value.identifier"
}
},
"locale.identifier": {
"$fk": "locale.identifier"
}
}
}
},
"Query": {
"products": {
"db": "mycorp-dev",
"collection": "d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content",
"find": {
"locale.identifier": {
"$in": {
"$arg": "_language"
}
},
"entityType": "product"
}
}
}
}
Der erste Anwendungsfall, der betrachtet wird, ist das sogenannte “Field to Field mapping”. Bei dieser Art Mapping wird einem Feld im Type ein entsprechendes Attribut der Daten zugewiesen. Ein Beispiel dafür ist in Zeile 3 zu sehen, bei dem das Feld Category.name aus dem Schema auf Attribut displayName aus den Daten verweist.
Der zweite Anwendungsfall ist das “Field to Query mapping”. Hierbei wird einem Feld im Type das Ergebnis einer Datenabfrage zugewiesen. Ein Beispiel für ein solches Mapping ist in Zeile 45ff. zu finden: das Feld Query.products wird abgebildet durch die Daten, die in der REST-Schnittstelle unter /mycorp-dev/d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content zu finden sind und den Filtern entityType": "product" und "locale.identifier": { "$in": { "$arg": "_language" } } entsprechen. Das bedeutet, dass genau die Produkte abgefragt werden, welche in der definierten Quelle liegen, eine Entität von “product” darstellen und eines der Sprachkürzel verwenden, die im Argument “_language” übergeben werden.
Ein weiteres Beispiel für ein “Field to Query mapping” ist ab Zeile 29 zu finden. In dieser Abbildungsdefinition werden die Produktkategorien, welche in separaten Datensätzen gepflegt sind, über eine Fremdschlüsselbeziehung identifiziert. Der komplette Eintrag von Zeile 29 bis 42 sagt aus, dass in dem Feld Product.categories alle Produktkategorien aufgeführt werden, die unter /mycorp-dev/d8db6f24-0bf8-4f48-be47-5e41d8d427fd.preview.content liegen, deren identifier im Feld formData.tt_categories.value.identifier hinterlegt sind und deren locale.identifier exakt dem entspricht, was im Produktdatensatz als locale.identifier vorhanden ist. Da ein Produkt mehrere Kategorien im Datensatz unter formData.tt_categories.value.identifier referenzieren kann, wird hier mit dem Schlüssel $in gearbeitet.
|
Werden in einem |
Verwenden der GraphQL-Applikation
Abfragen können nun an die GraphQL-Applikation gesendet werden.
curl --location --request POST 'https://REST-HOST:PORT/graphql/mycorp-dev___products' \
--header 'Authorization: Bearer <PERMITTED_APIKEY>' \
--header 'Content-Type: application/json' \
--data-raw '{"query": "query($lang: [String!]){products(_language: $lang) {name description categories {name} picture {name binaryUrl width height}}}", "variables": {"lang": ["DE"]}}'
Dieses Beispiel zeigt die Abfrage der GraphQL-Applikation mit curl. Die Applikation steht immer unter dem Pfad /graphql/<descriptor.uri> zur Verfügung. Durch diese Query werden Produktdaten abhängig von der Variable $lang abgefragt. Die Variable wird dem im Schema definierten Argument _language als Wert übergeben. Da in der GraphQL-App-Definition ein sinnvoller Standardwert für _language im Schema enthalten ist, ist die Verwendung von Variablen in diesem Szenario optional. Weitere Details zu Argumenten und Variablen können der GraphQL-Dokumentation entnommen werden.
5.1.3. GraphQL-Beispiel mit Aggregations
Durch Aggregationen können komplexere Abfragen an den CaaS gestellt werden. So können z.B. dynamisch Attribute zu den Dokumenten der Antwort hinzugefügt werden. Es können aber noch deutlich komplexere Aggregationen erstellt werden. Eine Liste der zur Verfügung stehenden Aggregation Stages und Operators ist hier zu finden.
{
"_id": "mytenantid-dev___pagerefs",
"descriptor": {
"name": "pagerefs",
"description": "Query PageRefs",
"enabled": true,
"uri": "mytenantid-dev___pagerefs"
},
"schema": "type PageRef { _id: String projectId: String } type Query{ pageRefs(projectId: String): [PageRef] }",
"mappings": {
"PageRefs": {
"count": "count"
},
"Query": {
"pageRefs":{
"db": "mytenantid-dev",
"collection": "641154a9-b90c-4b10-a5f7-38677cbb5abc.release.content",
"stages": [
{ "$match": { "fsType":"PageRef" }},
{ "$addFields": { "projectId": { "$arg": "projectId" } } }
]
}
}
}
}
5.2. Tutorials
5.2.1. Quickstart: GraphQL-Applikationen
Diese Anleitung beinhaltet das Anlegen und Benutzen von GraphQL-Applikationen. Um die Anleitung abzuschließen, ist ein Grundverständnis der REST-Schnittstelle in Bezug auf Authentifizierung und der Abfrage von Dokumenten notwendig.
GraphQL-Applikationen ermöglichen das Abfragen von CaaS-Dokumenten über eigene GraphQL API-Endpunkte. Dabei stellen die Endpunkte die Dokumentendaten in einem selbst-definierten Format/Schema bereit.
In den folgenden Schritten werden wir beispielhaft eine GraphQL-Applikation erzeugen und benutzen, um Dokumentendaten abzufragen. Zum Senden der HTTP Anfragen wird curl benutzt.
-
Erzeugen von Beispiel-Dokumenten
Wir beginnen mit dem Anlegen von Beispieldaten, indem wir zuerst eine Collection anlegen.
# set these once so you can re-use them for other commands TENANT='YOUR-TENANT-ID' API_KEY='YOUR-API-KEY' curl --location --request PUT "https://REST-HOST:PORT/$TENANT/posts" \ --header "Authorization: Bearer $API_KEY"Anschließend erzeugen wird Dokumente in der Collection.
# you can execute this multiple times to create many documents curl --location "https://REST-HOST:PORT/$TENANT/posts" \ --header "Authorization: Bearer $API_KEY" --header 'Content-Type: application/json' \ --data "{ \"content\": \"My post created at $(date)..\" }" -
Definieren des gewünschten GraphQL-Schemas
Nachdem die Dokumente angelegt sind, müssen wir ein Schema definieren, mit dem wir auf die Daten zugreifen können.
Wir werden ein simples Modell für die Beispieldokumente aus dem letzten Schritt benutzen. Es können jedoch komplexere Datenmodelle erzeugt werden.
Speichern der GraphQL-Schema-Definition (schema.gql)cat > schema.gql << EOF type BlogPost { content: String! } type Query { posts: [BlogPost!] } EOF -
GraphQL API-Endpunkt anlegen
Im nächsten Schritt legen wir die GraphQL-Applikation mit unserem Schema an, sodass automatisch ein API-Endpunkt provisioniert wird.
Zuerst müssen wir jedoch ein paar Details über die GraphQL-Applikation definieren, sodass CaaS weiß, wie der neue Endpunkt provisioniert wird und die Daten dafür bereitgestellt werden. Dazu müssen wir diese Informationen wie folgt in einer GraphQL-App-Definition festhalten.
Speichern der GraphQL-App-Definition (app.json)cat > app.json << EOF { "descriptor": { "name": "myposts", "description": "Example app to fetch blog posts.", "enabled": true, "uri": "${TENANT}___myposts" }, "mappings": { "Query": { "posts": { "db": "$TENANT", "collection": "posts", "find": { "content": { "\$exists": true } } } } } } EOFWir haben das Schema (
schema.gql) und die dazugehörige App-Definition (app.json) vorbereitet. Diese können wir nun zusammen nutzen, um die GraphQL-Applikation mit der REST-Schnittstelle anzulegen.Anlegen der GraphQL-Applikationcurl -X PUT \ -H "Authorization: Bearer $API_KEY" \ -F app=@app.json \ -F schema=@schema.gql \ https://REST-HOST:PORT/$TENANT/gql-apps/${TENANT}___myposts -
Abfragen von Daten mit dem neuen Endpunkt
CaaS hat nun automatisch unseren neuen Endpunkt mit unseren Definitionen provisioniert. Der Endpunkt ist unter folgender URL verfügbar:
https://REST-HOST:PORT/graphql/\{YOUR-TENANT-ID}___mypostsWir können nun Dokumentendaten mit diesem Endpunkt abfragen.
curl --location "https://REST-HOST:PORT/graphql/${TENANT}___myposts" \ --header "Authorization: Bearer $API_KEY" \ --header 'Content-Type: application/json' \ --data '{"query":"{ posts { content } }","variables":{}}'Die Antwort sollte ähnlich aussehen wie folgendes JSON:
{ "data": { "posts": [ { "content": "My post created at Tue Aug 8 17:08:32 CEST 2023.." }, { "content": "My post created at Tue Aug 8 17:12:23 CEST 2023.." } ] } }
|
Der Standardwert für die Seitengröße von GraphQL Abfragen beträgt 20. Sollten es notwendig sein, mehr als 20 Dokumente abzufragen, müssen Argumente für Pagination genutzt werden. Weitere Informationen können dem Bereich |
6. Hilfe
Der Technical Support der Crownpeak Technology GmbH bietet qualifizierte technische Unterstützung zu allen Themen, die FirstSpirit™ als Produkt betreffen. Weitere Hilfe zu vielen relevanten Themen erhalten und finden Sie in auch in unserer Community.