OBS/Kostenpflichtige Module/RESTServer/Endpunkte: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| Zeile 86: | Zeile 86: | ||
Limit überschritten, antwortet der Server mit '''413 Payload Too Large'''. Für | Limit überschritten, antwortet der Server mit '''413 Payload Too Large'''. Für | ||
Uploads gilt nicht das JSON-Body-Limit (10 MB), sondern dieses Endpunkt-Limit. | Uploads gilt nicht das JSON-Body-Limit (10 MB), sondern dieses Endpunkt-Limit. | ||
Der Originalname (beim resumable Upload über den Header <code>Upload-Metadata</code>) ist '''Pflicht'''; fehlt er, wird der Upload mit 413/400 abgelehnt. Dem Skript stehen Pfad, Name | Der Originalname (beim resumable Upload über den Header <code>Upload-Metadata</code>) ist '''Pflicht'''; fehlt er, wird der Upload mit 413/400 abgelehnt. Dem Skript stehen Pfad, Name, Content-Type und die SHA-256-Prüfsumme der gespeicherten Datei als <code>_OBS_UPLOAD_*</code>-Parameter zur Verfügung; bei <code>multipart/form-data</code> zusätzlich die übrigen Formularfelder als <code>_OBS_FORM_*</code> (Details: [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]]). | ||
Unterstützt werden zwei Übertragungsarten: | Unterstützt werden zwei Übertragungsarten: | ||
| Zeile 156: | Zeile 156: | ||
|- | |- | ||
| '''500''' || Skript- oder Syntax-Fehler (Details in <code>RESTSRV_PROTO</code>) | | '''500''' || Skript- oder Syntax-Fehler (Details in <code>RESTSRV_PROTO</code>) | ||
|- | |||
| '''405''' || Das Endpunkt-Skript hat für die angefragte HTTP-Methode keine Funktion; der Header <code>Allow</code> nennt die vorhandenen | |||
|- | |- | ||
| '''415''' || Datei-Upload an einen Endpunkt, der dafür nicht freigeschaltet ist (<code>re_upload = 0</code>) | | '''415''' || Datei-Upload an einen Endpunkt, der dafür nicht freigeschaltet ist (<code>re_upload = 0</code>) | ||
| Zeile 197: | Zeile 199: | ||
| Erster Aufruf läuft noch || '''503''' <code>IDEMPOTENCY_IN_PROGRESS</code> mit <code>Retry-After</code>. Beim nächsten Versuch liegt die gespeicherte Antwort vor | | Erster Aufruf läuft noch || '''503''' <code>IDEMPOTENCY_IN_PROGRESS</code> mit <code>Retry-After</code>. Beim nächsten Versuch liegt die gespeicherte Antwort vor | ||
|- | |- | ||
| Früherer Aufruf ohne Ergebnis || '''409''' <code>IDEMPOTENCY_UNRESOLVED</code>. | | Früherer Aufruf ohne Ergebnis || '''409''' <code>IDEMPOTENCY_UNRESOLVED</code>. Nur noch nach einem '''harten Abbruch''' des Dienstes zwischen Verarbeitung und Festschreiben; ob die Buchung stattgefunden hat, ist unbekannt. Der Aufräumlauf gibt solche Einträge nach 24 Stunden frei und protokolliert sie | ||
|} | |} | ||
| Zeile 204: | Zeile 206: | ||
* Antwortet das Skript mit '''2xx''', wird die Antwort gespeichert und bei einer Wiederholung erneut ausgeliefert. | * Antwortet das Skript mit '''2xx''', wird die Antwort gespeichert und bei einer Wiederholung erneut ausgeliefert. | ||
* Antwortet das Skript mit '''4xx''' (fachliche Ablehnung), wird der Schlüssel wieder '''freigegeben''' - der Konsument darf ihn nach Korrektur erneut verwenden. Sonst würde ein einziger Validierungsfehler den Schlüssel dauerhaft blockieren. | * Antwortet das Skript mit '''4xx''' (fachliche Ablehnung), wird der Schlüssel wieder '''freigegeben''' - der Konsument darf ihn nach Korrektur erneut verwenden. Sonst würde ein einziger Validierungsfehler den Schlüssel dauerhaft blockieren. | ||
* Endet die Verarbeitung mit '''5xx''' oder einem Skript-Fehler, | * Endet die Verarbeitung mit '''5xx''' oder einem Skript-Fehler, wird der Schlüssel '''freigegeben''' und der Fall protokolliert. Der Konsument darf denselben Schlüssel erneut senden. | ||
* Das ist eine bewusste Abwägung (geändert 2026-08-25): Bleibt der Schlüssel nach einem Serverfehler belegt, ist der Vorgang '''unwiederholbar''' - der Client bekommt dauerhaft 503 und müsste die erfasste Arbeit verwerfen. Garantierter Datenverlust wiegt schwerer als ein möglicher Doppelsatz. | |||
* '''Folge für die Auslegung:''' ein schreibender Endpunkt sollte selbst wiederholbar sein, etwa über ein fachliches Merkmal des Clients. Wo reines Anhängen stattfindet (Positionen, Dateien), bleibt sonst ein Restrisiko. | |||
Der Schlüssel gilt je '''Zugang, Methode und Pfad'''. Derselbe | Der Schlüssel gilt je '''Zugang, Methode und Pfad'''. Derselbe | ||
Version vom 31. August 2026, 06:03 Uhr
- A Preise aktualisieren
- C Personen übertragen
- E Kategorien verwalten
- G Kataloge verwalten
- I Merkliste übertragen
- K Varianten übertragen
- L Artikelvarianten übertragen
- M Referenzarten übertragen
- N Lagerbestände verwalten
- U Bestellungen einlesen
- V leere Passworte füllen
- W Update-Informationen zurücksetzen
- X Konfiguration
- Z Protokoll
Endpunkte
Ein Endpunkt stellt eine Adresse bereit, über die der REST-Server konkrete Funktionen anbietet. Jeder Endpunkt wird durch ein OBS-Skript oder einen WebHook realisiert und ist genau einem Server-Profil zugeordnet.
Routing über Pfad-Templates
Das Routing erfolgt über die Spalte Pfad-Template (re_pathtemplate).
Ein Template beschreibt den vollständigen Pfad nach dem Host und kann
Platzhalter enthalten:
- Statische Segmente müssen exakt übereinstimmen (Groß-/Kleinschreibung wird ignoriert).
- Platzhalter in geschweiften Klammern – z. B.
{uid}– passen auf einen beliebigen Wert und werden als Pfad-Parameter erfasst.
Beispiele für gültige Templates:
| Template | Passt auf | Pfad-Parameter |
|---|---|---|
/orders |
/orders |
– |
/orders/{uid} |
/orders/4711 |
uid = 4711
|
/orders/{uid}/modules/{code} |
/orders/4711/modules/A1 |
uid = 4711, code = A1
|
/kalender/v1 |
/kalender/v1 |
– |
Präzedenz bei mehreren Treffern
Passen mehrere Templates auf denselben Pfad, gewinnt das spezifischste –
also das mit den meisten statischen Segmenten. So schlägt /orders/summary
das Template /orders/{uid}, während /orders/4711 auf
/orders/{uid} matcht.
Hauptfelder eines Endpunkts
| Feld | Spalte | Zweck |
|---|---|---|
| Pfad-Template | re_pathtemplate |
Maßgeblich fürs Routing. Vollständiger Pfad mit Platzhaltern, z. B. /orders/{uid}/modules/{code}
|
| Server | re_server |
Zuordnung zum Server-Profil (erforderlich) |
| Aktiv | re_aktiv |
Statusflag; inaktive Endpunkte liefern 404 |
| Skript | re_script |
DwScript-Quelltext des Handlers (siehe Scripting) |
| WebHook | re_webhook |
optional: Verweis auf einen Einmal-Endpunkt statt Skript |
| Info | – | Dokumentations-Freitext |
| Datei-Upload | re_upload |
Erlaubt Datei-Uploads an diesem Endpunkt (0 = aus, 1 = an). Ohne Freigabe werden Upload-Anfragen mit 415 abgelehnt.
|
| Max. Upload-Grösse | re_upload_size |
Maximale Dateigrösse in MB. Leer/0 = Standard 25 MB. Überschreitung wird mit 413 abgelehnt. |
Pfad-Parameter im Skript
Die aus den Platzhaltern erfassten Werte stehen im Endpunkt-Skript als
reservierte Parameter mit Präfix _OBS_PATH_ zur Verfügung:
function Get(oParams: TStrings; oBody: TJSONObject): string;
var cUid: string;
begin
cUid := oParams.Values['_OBS_PATH_uid']; // aus /orders/{uid}
// ...
end;Da der Präfix _OBS_ für von außen gelieferte Header/Query-Parameter
gesperrt ist, können diese Werte nicht durch den Client überschrieben werden.
Datei-Uploads
Ein Endpunkt nimmt Datei-Uploads nur entgegen, wenn er dafür freigeschaltet ist
(re_upload = 1). Andernfalls werden Upload-Anfragen mit
415 Unsupported Media Type abgelehnt und das Skript wird nicht ausgeführt.
Die maximal zulässige Dateigrösse wird pro Endpunkt über re_upload_size
(in MB) festgelegt; ohne Angabe gilt der Standard von 25 MB. Wird das
Limit überschritten, antwortet der Server mit 413 Payload Too Large. Für
Uploads gilt nicht das JSON-Body-Limit (10 MB), sondern dieses Endpunkt-Limit.
Der Originalname (beim resumable Upload über den Header Upload-Metadata) ist Pflicht; fehlt er, wird der Upload mit 413/400 abgelehnt. Dem Skript stehen Pfad, Name, Content-Type und die SHA-256-Prüfsumme der gespeicherten Datei als _OBS_UPLOAD_*-Parameter zur Verfügung; bei multipart/form-data zusätzlich die übrigen Formularfelder als _OBS_FORM_* (Details: Scripting).
Unterstützt werden zwei Übertragungsarten:
- Einfacher Upload per
multipart/form-data(eine Datei pro Request). - Resumable/Chunked Upload per
Content-Range(grosse Dateien, fortsetzbar nach Abbruch).
Der Server legt die hochgeladene Datei in einem temporären Verzeichnis ab und übergibt dem Endpunkt-Skript den Pfad. Was mit der Datei geschieht (Ablage, DMS-Verknüpfung, Weiterverarbeitung), entscheidet allein das Skript. Details und Beispiele: Scripting.
HTTP-Methode
Welche Funktion aufgerufen wird, ergibt sich aus dem HTTP-Verb: Der Server ruft
die gleichnamige Skript-Methode auf (Get/Post/Put/Delete/Patch).
Ein Template entspricht damit einem Endpunkt-Skript; unterschiedliche
Pfad-Formen (z. B. /orders vs. /orders/{uid}) sind
eigene Endpunkt-Einträge mit eigenem Skript und eigener Berechtigung.
URL-Struktur
http://[Host][:Port][Pfad-Template]
Beispiele:
https://api.meinserver.de/ordershttps://api.meinserver.de/orders/4711https://api.meinserver.de/orders/4711/modules/A1
Versionierung
Da es kein eigenes Versions-Feld mehr gibt, wird die Version als statisches
Segment ins Template aufgenommen, z. B. /orders/v1 oder
/v1/orders/{uid}. Änderung ohne Breaking Change:
- Bestehenden Endpunkt unverändert lassen.
- Neuen Endpunkt mit gleichem Ressourcennamen, aber neuem Versions-Segment im Template anlegen.
- Berechtigungen für neue Konsumenten setzen.
- Alten Endpunkt deaktivieren, wenn die Migration abgeschlossen ist.
Zugriffskontrolle
Endpunkte sind Server-Profilen zugeordnet; ein Zugang benötigt eine explizite
Berechtigung (Tabelle RESTSRV_ACCESS), um einen Endpunkt nutzen zu
dürfen. Weil jede Pfad-Form ein eigener Endpunkt-Eintrag ist, lässt sich der
Zugriff pro Pfad-Form granular vergeben (z. B. Lesen von
/orders/{uid} erlauben, aber das ändernde
PUT /orders/{uid}/modules/{code} nicht).
Caching
Die Endpunkt-Definitionen werden pro Server-Profil zwischengespeichert (TTL, Standard 60 s). Neue oder geänderte Endpunkte/Templates werden daher erst nach Ablauf des Caches (bzw. nach einer Cache-Invalidierung) wirksam – nicht zwingend sofort.
HTTP-Fehlercodes
| Code | Ursache |
|---|---|
| 404 | Kein Template passt zum Pfad, Endpunkt inaktiv oder falsches Server-Profil |
| 403 | Zugang fehlt in der Berechtigungsliste |
| 401 | API-Key ungültig/fehlend, JWT abgelaufen oder Sitzung gesperrt (AUTH_EXPIRED) |
| 500 | Skript- oder Syntax-Fehler (Details in RESTSRV_PROTO)
|
| 405 | Das Endpunkt-Skript hat für die angefragte HTTP-Methode keine Funktion; der Header Allow nennt die vorhandenen
|
| 415 | Datei-Upload an einen Endpunkt, der dafür nicht freigeschaltet ist (re_upload = 0)
|
| 413 | Hochgeladene Datei überschreitet die zulässige Maximalgrösse (re_upload_size)
|
| 429 | Rate-Limit überschritten; die Antwort enthält den Header Retry-After
|
| 503 | Eine Anfrage mit demselben Idempotency-Key wird gerade verarbeitet; die Antwort enthält Retry-After
|
| 409 | Ein früherer Aufruf mit demselben Idempotency-Key ist ohne Ergebnis geblieben (IDEMPOTENCY_UNRESOLVED)
|
| 422 | Derselbe Idempotency-Key wurde mit anderem Inhalt gesendet (IDEMPOTENCY_KEY_REUSED)
|
| 400 | Die Anfrage wurde unverschlüsselt an einen TLS-Port geschickt (http statt https). Die Abweisung erfolgt vor Authentifizierung und Endpunkt-Skript
|
Jede Fehlerantwort besteht aus einem error-Objekt mit
maschinenlesbarem Code - Aufbau siehe
Übersicht.
Daneben kann ein Endpunkt-Skript den Statuscode selbst setzen (z.B. 201, 204, 409, 422) sowie Response-Header wie ETag oder Location - siehe Scripting.
Idempotenz
Schickt ein Konsument bei POST, PUT, PATCH
oder DELETE den Header Idempotency-Key, sorgt der Server
selbst dafür, dass eine wiederholte Sendung keine Zweitwirkung hat. Das gilt
für jeden Endpunkt - es muss weder am Endpunkt etwas eingestellt noch im
Skript etwas programmiert werden.
| Situation | Antwort des Servers |
|---|---|
| Erster Aufruf | Endpunkt läuft normal, das Ergebnis wird zum Schlüssel gespeichert |
| Wiederholung, gleicher Inhalt | Gespeicherte Antwort (gleicher Statuscode, gleicher Body, gleiche Header) plus Header Idempotent-Replay: true. Das Skript läuft nicht
|
| Wiederholung, anderer Inhalt | 422 IDEMPOTENCY_KEY_REUSED - derselbe Schlüssel für einen anderen Inhalt ist ein Client-Fehler
|
| Erster Aufruf läuft noch | 503 IDEMPOTENCY_IN_PROGRESS mit Retry-After. Beim nächsten Versuch liegt die gespeicherte Antwort vor
|
| Früherer Aufruf ohne Ergebnis | 409 IDEMPOTENCY_UNRESOLVED. Nur noch nach einem harten Abbruch des Dienstes zwischen Verarbeitung und Festschreiben; ob die Buchung stattgefunden hat, ist unbekannt. Der Aufräumlauf gibt solche Einträge nach 24 Stunden frei und protokolliert sie
|
Wichtig für die Auslegung eines Endpunkts:
- Antwortet das Skript mit 2xx, wird die Antwort gespeichert und bei einer Wiederholung erneut ausgeliefert.
- Antwortet das Skript mit 4xx (fachliche Ablehnung), wird der Schlüssel wieder freigegeben - der Konsument darf ihn nach Korrektur erneut verwenden. Sonst würde ein einziger Validierungsfehler den Schlüssel dauerhaft blockieren.
- Endet die Verarbeitung mit 5xx oder einem Skript-Fehler, wird der Schlüssel freigegeben und der Fall protokolliert. Der Konsument darf denselben Schlüssel erneut senden.
- Das ist eine bewusste Abwägung (geändert 2026-08-25): Bleibt der Schlüssel nach einem Serverfehler belegt, ist der Vorgang unwiederholbar - der Client bekommt dauerhaft 503 und müsste die erfasste Arbeit verwerfen. Garantierter Datenverlust wiegt schwerer als ein möglicher Doppelsatz.
- Folge für die Auslegung: ein schreibender Endpunkt sollte selbst wiederholbar sein, etwa über ein fachliches Merkmal des Clients. Wo reines Anhängen stattfindet (Positionen, Dateien), bleibt sonst ein Restrisiko.
Der Schlüssel gilt je Zugang, Methode und Pfad. Derselbe
Idempotency-Key an einem anderen Endpunkt ist damit ein eigener
Vorgang - der Konsument muss ihn nicht global eindeutig vergeben, aber pro Vorgang
stabil wiederverwenden (also nicht bei jedem Wiederholversuch neu erzeugen).
Die Einträge stehen in RESTSRV_IDEMPOTENCY und werden nach 30 Tagen
automatisch aufgeräumt. Einträge ohne Ergebnis werden nicht automatisch
gelöscht, sondern im Protokoll gemeldet.
WebHooks
WebHooks sind Einmal-Endpunkte für asynchrone Callbacks. Beim ersten
erfolgreichen Aufruf wird die Antwort in der Tabelle REMOTE_HOOK_URL
gespeichert und der Endpunkt anschließend automatisch gelöscht.
Typischer Einsatz: OBS stösst einen Vorgang bei einem Fremdsystem an (Bezahldienst, Versanddienstleister) und gibt diesem eine Rückruf-Adresse mit, die nur ein einziges Mal gültig ist. Damit kann die Adresse nicht später erneut - oder von jemand anderem - benutzt werden.
Ablauf:
- OBS legt einen Eintrag in
REMOTE_HOOK_URLan und dazu einen Endpunkt, dessen Feld WebHook (re_webhook) auf diesen Eintrag zeigt. Ein Skript wird für diesen Endpunkt nicht gepflegt. - Die Adresse dieses Endpunkts wird dem Fremdsystem als Callback-URL übergeben.
- Das Fremdsystem ruft die Adresse auf. Der Server legt den übergebenen Inhalt in
REMOTE_HOOK_URL.hu_responseab, antwortet mit{"status": "ok"}und löscht den Endpunkt. - Der weiterverarbeitende OBS-Prozess findet die Rückmeldung in
hu_response.
existiert nicht mehr, die Antwort ist 404. Das ist gewollt - ein WebHook ist keine dauerhafte Schnittstelle. Für eine dauerhaft erreichbare Rückmelde-Adresse einen
normalen Endpunkt mit Skript anlegen.