OBS/Kostenpflichtige Module/RESTServer: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Idempotency-Key als Pflicht, Abschnitt Keep-alive, HSTS, vollstaendige Konsolenbefehle; Ablaufliste und Protokollverhalten berichtigt [Volltext ersetzt] |
||
| Zeile 96: | Zeile 96: | ||
# Rate-Limit-Prüfung (pro API-Key bzw. IP und global, Schwellen je Server-Profil) | # Rate-Limit-Prüfung (pro API-Key bzw. IP und global, Schwellen je Server-Profil) | ||
# Andrangsgrenze des Server-Profils (''Max. parallel'') - bei Überschreitung '''503''' mit ''Retry-After'' | |||
# Authentifizierung über den API-Key (Header ''apikey'') | # Authentifizierung über den API-Key (Header ''apikey'') | ||
# CORS-Prüfung (sofern ''Origin''-Header gesetzt) | # CORS-Prüfung (sofern ''Origin''-Header gesetzt) | ||
| Zeile 101: | Zeile 102: | ||
# Routing: Auflösung des Pfads über die Pfad-Templates der Endpunkte | # Routing: Auflösung des Pfads über die Pfad-Templates der Endpunkte | ||
# Prüfung der Berechtigung (Zugang -> Endpunkt) | # Prüfung der Berechtigung (Zugang -> Endpunkt) | ||
# Idempotenz-Prüfung | # Entpacken des Anfragekörpers, sofern er mit ''Content-Encoding: gzip'' gesendet wurde | ||
# Idempotenz-Prüfung bei POST/PUT/PATCH/DELETE - der Header ''Idempotency-Key'' ist dort '''Pflicht''' | |||
# Ausführung des Endpunkt-Skripts (oder WebHook-Antwort) | # Ausführung des Endpunkt-Skripts (oder WebHook-Antwort) | ||
# Festschreiben des Ergebnisses im Idempotenz-Speicher (sofern in Schritt | # Festschreiben des Ergebnisses im Idempotenz-Speicher (sofern in Schritt 9 reserviert) | ||
# JSON-Antwort | # JSON-Antwort und Statistik-Eintrag | ||
{{Hinweis|'''Die Reihenfolge ist kein Zufall.''' Das Entpacken liegt '''hinter''' | |||
der Authentifizierung, damit ein Unbefugter dem Server keine Rechenzeit für eine | |||
Dekompressionsbombe abverlangen kann - und '''vor''' der Idempotenz-Reservierung, | |||
damit eine abgewiesene Anfrage keinen ''Idempotency-Key'' verbrennt. | |||
'''Der Normalfall erzeugt keine Protokollzeile.''' Bis 08/2026 schrieb jede | |||
Anfrage eine Zeile nach RESTSRV_PROTO; sie ist entfallen, weil RESTSRV_STATS | |||
zu derselben Anfrage IP, Zugang, Endpunkt, Methode, Pfad, Status, Laufzeit und | |||
dieselbe Korrelations-ID trägt - und länger aufbewahrt wird. Das Protokoll trägt | |||
seitdem nur noch Auffälligkeiten.}} | |||
==Adressierung== | ==Adressierung== | ||
| Zeile 122: | Zeile 135: | ||
==Unterstützte HTTP-Methoden== | ==Unterstützte HTTP-Methoden== | ||
Der Server akzeptiert die Methoden '''GET''', '''POST''', '''PUT''', '''DELETE''' und '''PATCH''' sowie '''OPTIONS''' (CORS-Preflight, ohne Skript-Aufruf). Jede Methode wird im Endpunkt-Skript als gleichnamige | Der Server akzeptiert die Methoden '''GET''', '''POST''', '''PUT''', '''DELETE''' und '''PATCH''' sowie '''OPTIONS''' (CORS-Preflight, ohne Skript-Aufruf). Jede Methode wird im Endpunkt-Skript als gleichnamige Prozedur implementiert - '''mit einer Ausnahme''': ''Delete'' ist in der Skriptsprache ein reservierter Name und lässt sich nicht als Prozedur deklarieren. Siehe [[OBS/Kostenpflichtige Module/RESTServer/Scripting|Scripting]]. | ||
Fehlt die zur Methode passende Prozedur, antwortet der Server mit '''405''' und | |||
nennt im Header ''Allow'' die Verben, die dieses Skript tatsächlich anbietet. | |||
==Kompression== | ==Kompression== | ||
| Zeile 130: | Zeile 146: | ||
Gepackt wird nur, wo es etwas bringt: | Gepackt wird nur, wo es etwas bringt: | ||
* Nur JSON, XML, Text, CSV und | * Nur JSON (auch ''problem+json'' und ''ndjson''), XML, JavaScript, SVG und alles unter ''text/'' - darunter Text, CSV und HTML. Bereits komprimierte Typen - PDF, Bild, ZIP, Video - werden durch gzip '''grösser''', nicht kleiner. | ||
* Erst ab '''1024 Byte'''. Darunter kostet der gzip-Rahmen mehr, als der Inhalt einspart. | * Erst ab '''1024 Byte'''. Darunter kostet der gzip-Rahmen mehr, als der Inhalt einspart. | ||
* '''Nicht''' bei Dateiantworten, nicht bei Teilauslieferungen (206) und nicht bei Antworten ohne Körper (204, 304). | * '''Nicht''' bei Dateiantworten, nicht bei Teilauslieferungen (206) und nicht bei Antworten ohne Körper (204, 304). | ||
| Zeile 162: | Zeile 178: | ||
* '''10 MB''' absolut. Dieselbe Grenze, die auch für einen ungepackten Körper gilt. | * '''10 MB''' absolut. Dieselbe Grenze, die auch für einen ungepackten Körper gilt. | ||
* '''das 400fache''' der gesendeten Grösse. Damit wird eine ''Dekompressionsbombe'' - wenige Kilobyte, die sich auf Hunderte Megabyte aufblähen - schon nach wenigen Prozent abgebrochen. | * '''das 400fache''' der gesendeten Grösse, '''mindestens aber 64 KB'''. Damit wird eine ''Dekompressionsbombe'' - wenige Kilobyte, die sich auf Hunderte Megabyte aufblähen - schon nach wenigen Prozent abgebrochen. Der Boden von 64 KB sorgt dafür, dass die Verhältnisrechnung winzige Körper gar nicht erst trifft: ein 100-Byte-Körper darf sich auf 64 KB entpacken, nicht nur auf 40 KB. | ||
Die zweite Grenze trifft normale Nutzlasten nicht. Gemessen erreichen echte JSON-Körper Verhältnisse von 24:1 bis 40:1, und selbst eine Liste aus zehntausenden identischen Zeilen kommt nur auf rund 340:1 - mehr gibt das Verfahren für wiederholte Datensätze nicht her. Über 400:1 kommt nur, wer sehr lange Läufe desselben Zeichens sendet. | Die zweite Grenze trifft normale Nutzlasten nicht. Gemessen erreichen echte JSON-Körper Verhältnisse von 24:1 bis 40:1, und selbst eine Liste aus zehntausenden identischen Zeilen kommt nur auf rund 340:1 - mehr gibt das Verfahren für wiederholte Datensätze nicht her. Über 400:1 kommt nur, wer sehr lange Läufe desselben Zeichens sendet. | ||
Für Datei-Uploads gilt keine der beiden Grenzen - dort zählt allein die je Endpunkt eingestellte Maximalgrösse.}} | Für Datei-Uploads gilt keine der beiden Grenzen - dort zählt allein die je Endpunkt eingestellte Maximalgrösse.}} | ||
==Persistente Verbindungen (Keep-alive)== | |||
Der Server hält eine Verbindung nach der Antwort '''offen''', statt sie zu | |||
schliessen. Ein Client, der mehrere Anfragen hintereinander stellt - eine App, | |||
die eine Liste seitenweise abholt -, spart damit je Folgeanfrage den Aufbau von | |||
TCP-Verbindung und TLS-Sitzung. | |||
{| class="wikitable" | |||
! Grenze !! Wert !! Bedeutung | |||
|- | |||
| Leerlauf || '''10 Sekunden''' || Passiert auf der Verbindung so lange nichts, wird sie geschlossen | |||
|- | |||
| Anfragen je Verbindung || '''100''' || Danach schliesst der Server geordnet, der Client baut neu auf | |||
|} | |||
Beides ist für den Konsumenten unkritisch: Eine geschlossene Verbindung ist kein | |||
Fehler, jede HTTP-Bibliothek baut sie bei der nächsten Anfrage selbst wieder auf. | |||
Wer viele Anfragen hintereinander stellt, gewinnt aber deutlich, wenn er seinen | |||
Client die Verbindung wiederverwenden lässt (''Connection: keep-alive'' ist der | |||
Standard von HTTP/1.1, die meisten Bibliotheken tun es von allein). | |||
{{Hinweis|'''Die Leerlaufgrenze gilt für jeden Lesevorgang der Verbindung''', | |||
nicht nur für das Warten auf die nächste Anfrage. Ein Client, der seinen | |||
Anfragekörper nur tropfenweise sendet und dazwischen länger als 10 Sekunden | |||
pausiert, verliert die Verbindung mitten im Senden.}} | |||
Die Werte sind bewusst knapp gewählt: Der Server fährt einen eigenen Thread je | |||
Verbindung, eine leerlaufende Verbindung kostet also nicht bloss einen | |||
Dateizeiger. Sie sind keine Lastgrenze - dafür gibt es ''Max. Verbindungen'' und | |||
''Max. parallel'' am Server-Profil (siehe | |||
[[OBS/Kostenpflichtige Module/RESTServer/Server-Profile|Server-Profile]]). | |||
==Datei-Uploads== | ==Datei-Uploads== | ||
| Zeile 182: | Zeile 230: | ||
Ein Client, der nach einem Timeout dieselbe Anfrage erneut schickt, darf keine | Ein Client, der nach einem Timeout dieselbe Anfrage erneut schickt, darf keine | ||
Zweitbuchung auslösen. Der Server erledigt das selbst: | Zweitbuchung auslösen. Der Server erledigt das selbst: Jeder Aufruf mit | ||
'''POST''', '''PUT''', '''PATCH''' oder '''DELETE''' den Header | '''POST''', '''PUT''', '''PATCH''' oder '''DELETE''' muss den Header | ||
<code>Idempotency-Key</code> | <code>Idempotency-Key</code> tragen; der Server merkt sich Schlüssel und Ergebnis | ||
'''RESTSRV_IDEMPOTENCY'''. Eine Wiederholung mit demselben Schlüssel und demselben | in '''RESTSRV_IDEMPOTENCY'''. Eine Wiederholung mit demselben Schlüssel und | ||
Inhalt bekommt die '''gespeicherte Antwort''' zurück - das Endpunkt-Skript läuft | demselben Inhalt bekommt die '''gespeicherte Antwort''' zurück - das | ||
gar nicht erst an. | Endpunkt-Skript läuft gar nicht erst an. | ||
{{Achtung|'''Der Header ist Pflicht, nicht optional.''' Ein schreibender Aufruf | |||
'''ohne''' <code>Idempotency-Key</code> wird mit '''400''' | |||
<code>IDEMPOTENCY_KEY_MISSING</code> abgewiesen, und das Endpunkt-Skript läuft | |||
nicht an. | |||
Das war bis v1.21 anders: fehlte der Header, lief die Anfrage ungeschützt durch. | |||
Der Schutz gegen eine Doppelbuchung stand damit in der Zusage des Clients und | |||
nicht in einer Prüfung des Servers - ein Wiederholversuch nach Zeitüberschreitung | |||
buchte ein zweites Mal. Konsumenten, die bisher ohne den Header schreiben, müssen | |||
angepasst werden.}} | |||
* ''' | * '''Pflicht nur für schreibende Verben.''' ''GET'' braucht keinen Schlüssel und kennt die Mechanik nicht. | ||
* '''Kein Schalter am Endpunkt.''' Die Mechanik greift automatisch | * '''Der JWT-Endpunkt ist ausgenommen.''' Anmelden, Erneuern und Abmelden laufen vor der Adressauflösung und brauchen keinen Schlüssel. | ||
* '''Das Skript muss nichts tun.''' Eine eigene Idempotenz-Logik im Skript ist nicht | * '''Kein Schalter am Endpunkt.''' Die Mechanik greift für jeden Endpunkt automatisch. | ||
* '''Das Skript muss nichts tun.''' Eine eigene Idempotenz-Logik im Skript ist nicht nötig. | |||
* '''Pro Vorgang ein Schlüssel''', über alle Wiederholversuche hinweg unverändert - nicht bei jedem Versuch neu erzeugt. | |||
Details und die Statuscodes: [[OBS/Kostenpflichtige Module/RESTServer/ | Details und die Statuscodes: [[OBS/Kostenpflichtige Module/RESTServer/Endpunkte|Endpunkte]], Abschnitt Idempotenz. | ||
==Sitzungen und Abmelden== | ==Sitzungen und Abmelden== | ||
| Zeile 208: | Zeile 269: | ||
* '''Abmelden wirkt sofort.''' Ein ''DELETE'' auf den JWT-Endpunkt sperrt die Sitzung; alle Token dieser Sitzung sind damit unmittelbar ungültig, auch die noch nicht abgelaufenen. Anmelden, Erneuern und Abmelden laufen also über einen einzigen Endpunkt, und für das Abmelden ist kein Skript nötig. | * '''Abmelden wirkt sofort.''' Ein ''DELETE'' auf den JWT-Endpunkt sperrt die Sitzung; alle Token dieser Sitzung sind damit unmittelbar ungültig, auch die noch nicht abgelaufenen. Anmelden, Erneuern und Abmelden laufen also über einen einzigen Endpunkt, und für das Abmelden ist kein Skript nötig. | ||
* '''Ein Refresh-Token gilt genau einmal.''' Beim Erneuern wird es entwertet. Wird es später erneut vorgelegt, gilt das als Diebstahl oder Fehlfunktion: die betroffene Sitzung wird komplett gesperrt und der Vorfall protokolliert. | * '''Ein Refresh-Token gilt genau einmal.''' Beim Erneuern wird es entwertet. Wird es später erneut vorgelegt, gilt das als Diebstahl oder Fehlfunktion: die betroffene Sitzung wird komplett gesperrt und der Vorfall protokolliert. | ||
* '''Alle Geräte abmelden.''' Ein gewöhnlicher Endpunkt kann über | * '''Alle Geräte abmelden.''' Ein gewöhnlicher Endpunkt kann über den Aufruf ''oWriter.JwtRevoke('all')'' auch alle Sitzungen eines Benutzers sperren - der Support-Fall „Gerät verloren". | ||
{{Achtung|Mit der Einführung dieser Prüfung verlieren '''alle vorher | {{Achtung|Mit der Einführung dieser Prüfung verlieren '''alle vorher | ||
| Zeile 259: | Zeile 320: | ||
* '''Geblockte Header:''' ''authorization'', ''cookie'', ''proxy-authorization'', ''x-forwarded-for'', ''x-real-ip'', ''apikey'', ''api_key'' werden nicht an das Skript durchgereicht. | * '''Geblockte Header:''' ''authorization'', ''cookie'', ''proxy-authorization'', ''x-forwarded-for'', ''x-real-ip'', ''apikey'', ''api_key'' werden nicht an das Skript durchgereicht. | ||
* '''TLS:''' Bei Profilen mit aktivem TLS fährt der Server ohne Zertifikat und Key nicht hoch. Plain-HTTP ist nur für ein dediziertes Debug-Profil möglich. | * '''TLS:''' Bei Profilen mit aktivem TLS fährt der Server ohne Zertifikat und Key nicht hoch. Plain-HTTP ist nur für ein dediziertes Debug-Profil möglich. | ||
* '''HSTS:''' Antworten eines TLS-Profils tragen ''Strict-Transport-Security: max-age=31536000; includeSubDomains''. Ein Browser spricht die Adresse danach ein Jahr lang nur noch über HTTPS an. Beim Debug-Profil ''Kein SSL'' wird der Header bewusst '''nicht''' gesetzt - der Browser würde ihn sonst speichern und die Erzwingung auch auf produktive Sitzungen anwenden. | |||
* '''mTLS''' (Mutual TLS): erzwingt, dass jeder Client ein gültiges Client-Zertifikat vorlegt. Optional kann pro Zugang ein erwarteter Subject-DN hinterlegt werden. | * '''mTLS''' (Mutual TLS): erzwingt, dass jeder Client ein gültiges Client-Zertifikat vorlegt. Optional kann pro Zugang ein erwarteter Subject-DN hinterlegt werden. | ||
* '''DNS-Cache:''' Host-zu-IP-Auflösungen für die Zugangs-Host-Prüfung werden 5 Minuten gecached. | * '''DNS-Cache:''' Host-zu-IP-Auflösungen für die Zugangs-Host-Prüfung werden 5 Minuten gecached. | ||
| Zeile 268: | Zeile 330: | ||
==Statistik== | ==Statistik== | ||
Die Tabelle '''RESTSRV_STATS''' enthält eine Statistik aller bearbeiteten Anfragen mit Zugang, Endpunkt, Methode, HTTP-Status und Laufzeit in Millisekunden. Aufruf der Statistik: | Die Tabelle '''RESTSRV_STATS''' enthält eine Statistik aller bearbeiteten Anfragen | ||
mit IP, Zugang, Endpunkt, Methode, angefragtem Pfad, HTTP-Status und Laufzeit in | |||
Millisekunden. Dazu kommen zwei Felder, die den Sprung ins Protokoll erlauben: | |||
* '''rs_trace''' - dieselbe Korrelations-ID, die auch im Header ''X-Trace-Id'' und in jeder zugehörigen Protokollzeile steht. Damit findet man zu einer auffälligen Statistikzeile alle Protokolleinträge derselben Anfrage. | |||
* '''rs_server''' - das Server-Profil, über das die Anfrage hereinkam. Bei mehreren Profilen (Public-TLS neben Internal-mTLS) ist das die einzige Angabe, an der sich der Weg ablesen lässt. | |||
Weil der Normalfall keine Protokollzeile mehr schreibt, ist RESTSRV_STATS die | |||
vollständige Sicht auf den Betrieb - RESTSRV_PROTO die auf die Auffälligkeiten. | |||
Aufruf der Statistik: | |||
* Aus der Endpunkt-Liste: F8 zeigt die Statistik des markierten Endpunkts. | * Aus der Endpunkt-Liste: F8 zeigt die Statistik des markierten Endpunkts. | ||
| Zeile 275: | Zeile 347: | ||
==Konsole== | ==Konsole== | ||
Wird der REST-Server nicht als Dienst, sondern interaktiv gestartet, erscheint eine farbige Konsole mit Live-Log. | Wird der REST-Server nicht als Dienst, sondern interaktiv gestartet, erscheint eine | ||
farbige Konsole mit Live-Log und einem '''fixierten Kopfbereich''', der die gerade | |||
laufenden Anfragen zeigt und sich fortlaufend aktualisiert. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Befehl | ! Befehl !! Wirkung | ||
|- | |- | ||
| ''show < | | ''show <handle>'' || Details einer Anfrage: Request-Header, Protokollzeilen, Antwort. JSON wird farbig formatiert. ''<handle>'' ist die Kennung aus der Abschlusszeile der Anfrage (z.B. ''7F''), '''keine''' laufende Nummer | ||
|- | |||
| ''1'' … ''9'' || Auswahl im Kopfbereich - kürzer als ''show'' für die gerade sichtbaren Anfragen. Mit ''mouse on'' auch per Klick | |||
|- | |||
| ''ps'' || Listet die gerade laufenden Anfragen auf | |||
|- | |||
| ''level <stufe>'' || Anzeigestufe des Live-Logs: ''quiet'' , ''normal'' oder ''debug''. Ohne Parameter wird die aktuelle Stufe genannt | |||
|- | |||
| ''filter <ausdruck>'' || Blendet aus, was nicht passt: ''path=<text>'', ''account=<name>'', ''status>=<code>''. ''filter aus'' hebt die Einschränkung auf | |||
|- | |||
| ''panel on|off'' || Fixierten Kopfbereich ein-/ausschalten. '''Ausgeschaltet''' lässt sich der Rückblick-Puffer des Konsolenfensters wieder scrollen | |||
|- | |||
| ''mouse on|off'' || Klick-Auswahl im Kopfbereich. '''Eingeschaltet''' ist das Markieren von Text mit der Maus nicht mehr möglich | |||
|- | |||
| ''help'' / ''?'' || Zeigt diese Liste in der Konsole | |||
|- | |- | ||
| ''exit'' / ''quit'' || Beendet den Server geordnet | | ''exit'' / ''quit'' || Beendet den Server geordnet | ||
|} | |} | ||
{{Hinweis|Der Anzeigefilter wirkt '''nur auf die Anzeige'''. Was die Konsole | |||
ausblendet, steht vollständig in RESTSRV_PROTO - es geht nichts verloren.}} | |||
Im Service-Modus (Windows-Dienst) ist die Konsole nicht sichtbar. Alle Einträge landen dort ausschliesslich in der Tabelle RESTSRV_PROTO. | Im Service-Modus (Windows-Dienst) ist die Konsole nicht sichtbar. Alle Einträge landen dort ausschliesslich in der Tabelle RESTSRV_PROTO. | ||
Aktuelle Version vom 25. September 2026, 10:28 Uhr
REST-Server
Was leistet der REST-Server?
Der REST-Server ist die universelle Schnittstelle Ihrer OBS-Installation nach außen. Er macht aus Ihrem OBS einen Dienst, mit dem andere Programme - Webseiten, Apps, Geräte, Kundensysteme, Cloud-Dienste - direkt sprechen können. Statt Daten manuell zu exportieren, zu mailen oder über Umwege bereitzustellen, holen sich angebundene Systeme genau die Information, die sie brauchen, in dem Moment, in dem sie sie brauchen - oder liefern neue Daten direkt in OBS ab.
Für Anwender, die nicht selbst programmieren, bedeutet das: Was bisher nur manuell, per Datei-Import oder über Spezialschnittstellen ging, lässt sich jetzt automatisieren. Eine Webseite zeigt live aktuelle Lagerbestände. Mitarbeiter erfassen Zeiten über das Handy, ohne dass jemand Excel-Listen einpflegen muss. Ein Kunde stößt per Bestelltaste in seinem System einen Vorgang in Ihrem OBS an. Ein Lieferant meldet Wareneingänge automatisch zurück. Jeder dieser Anwendungsfälle wird einmal eingerichtet und läuft danach automatisch.
Technisch gesehen ist der REST-Server ein in OBS integrierter, voll konfigurierbarer HTTP/HTTPS-Dienst, dessen Endpunkte über in OBS gepflegte Pascal-Skripte realisiert werden. Jeder Endpunkt bekommt eine eigene Adresse, eine eigene Logik und eine eigene Berechtigungsstruktur. Rückgaben erfolgen ausschliesslich im JSON-Format. Damit lassen sich beliebige Lese- und Schreibvorgänge auf der OBS-Datenbank realisieren, ohne dass externe Systeme direkten Datenbank-Zugriff erhalten - das ganze OBS-Regelwerk (Rechte, Validierung, Geschäftslogik) bleibt aktiv.
Im Ergebnis ist der REST-Server kein einzelnes Feature, sondern ein Werkzeugkasten: Was an Daten oder Funktionen in OBS verfügbar ist, kann über den REST-Server auch nach außen angeboten - oder von außen entgegengenommen - werden. Die Bandbreite reicht vom einfachen Lese-Endpunkt für ein Webseiten-Widget bis hin zu kompletten B2B-Integrationen mit Mandanten- und Rollen-Trennung.
Aufruf des Moduls in OBS: Stammdaten -> Z Weitere Stammdaten -> REST-Server
Anwendungsbereiche
Die folgenden Einsatzfälle sind typische Beispiele, an denen sich der praktische Nutzen ablesen lässt. Es ist keine abschliessende Liste - alles, was sich in OBS-Skripten abbilden lässt, kann auch über einen Endpunkt bereitgestellt werden.
Webseiten und Kundenportale
- Live-Daten auf der eigenen Webseite: Lagerbestände, Verfügbarkeiten, Preise, Auftragsstatus aus OBS direkt anzeigen, ohne tägliche Datei-Exports.
- Kundenportale: Kunden sehen ihre offenen Posten, Auftragshistorie, Lieferscheine. Die Seite holt sich die Daten zur Anzeigezeit direkt aus OBS, jeder Kunde sieht nur seine eigenen Daten.
- Trackingseiten: Status einer Bestellung, eines Auftrags oder einer Reparatur für Endkunden, abrufbar über eine Sendungsnummer.
Mobile Anwendungen und Außendienst
- Mobile Zeiterfassung: Mitarbeiter buchen Anfang, Pause und Ende über Smartphone oder Tablet, die Daten landen direkt in OBS - ohne Zettelwirtschaft.
- QR-/Barcode-Scanner und Lagergeräte: Wareneingang, Inventur, Kommissionierung direkt in OBS abbilden, ohne zwischengeschaltete Software.
- Außendienst-Apps: Techniker sehen ihre Aufträge, dokumentieren Einsätze, erfassen Material - synchronisiert mit OBS.
Anbindung von Drittsystemen
- Webshops: Bestellungen werden direkt vom Shop in OBS gemeldet, Lagerbestände und Preise vom Shop bei OBS abgefragt.
- Buchhaltungs- und ERP-Systeme: Bidirektionaler Austausch von Belegen, Stammdaten und Buchungen.
- CRM- und Marketing-Tools: Personendaten, Aktivitäten oder Mailing-Empfänger werden synchron gehalten.
- Logistikdienstleister: Versandaufträge werden übergeben, Tracking-Informationen zurückgeliefert.
Automatisierte Rückmeldungen (WebHooks)
- Zahlungs-Callbacks: Bezahldienste (z.B. PayPal, Klarna, Stripe) melden den Zahlungseingang an einen WebHook-Endpunkt - OBS bucht automatisch.
- Versanddienste: Statusmeldungen (verschickt, zugestellt, retour) werden direkt im passenden Vorgang dokumentiert.
- Cloud-Workflows: Externe Automatisierungs-Plattformen (Make, Zapier, n8n, ...) stoßen OBS-Vorgänge an oder werden von OBS aus angesprochen.
Geschäftspartner-Kommunikation (B2B)
- Lieferanten-Schnittstelle: Bestellungen werden automatisch übergeben, Auftragsbestätigungen und Lieferavise zurückgespielt.
- Kunden-Schnittstelle: Grosskunden bestellen direkt aus ihrem ERP heraus, Stammdaten und Konditionen werden zentral gepflegt.
- Sichere Maschine-zu-Maschine-Kommunikation: Mit Mutual-TLS (mTLS) wird sichergestellt, dass nur die freigeschalteten Partnersysteme - und niemand sonst - mit OBS sprechen können.
Interne Microservices und Automatisierungen
- Eigene kleine Hilfs-Tools: Zeitschaltautomatik, Reporting-Generator, Sammelaktionen, die aus mehreren Quellen Daten in OBS verarbeiten.
- Verbindung mehrerer Standorte: Verteilte Systeme tauschen Daten über definierte Endpunkte aus, ohne offene Datenbankverbindungen.
- Datenbereitstellung für Dashboards und Auswertungen: BI-Tools (Power BI, Grafana, ...) lesen aufbereitete Kennzahlen direkt aus OBS.
Was bedeutet das wirtschaftlich?
- Manuelle Arbeit fällt weg. Daten werden nicht mehr aus OBS exportiert, per Mail geschickt und woanders eingelesen - sie fliessen direkt.
- Fehler werden weniger. Jede manuelle Stelle ist eine mögliche Fehlerquelle; jede Automatisierung eine Stelle, an der nichts mehr schiefgehen kann.
- Neue Geschäftsmodelle werden möglich. Kunden- und Lieferantenportale, Self-Service-Funktionen, App-Anbindungen lassen sich aufbauen, ohne ein zweites System pflegen zu müssen.
- Bestehende Software bleibt verbunden. Statt eine vorhandene Anwendung ablösen zu müssen, kann sie über den REST-Server an OBS angedockt werden - in beiden Richtungen.
- Skaliert mit: Was klein anfängt (ein einzelner Endpunkt für eine Webseite) kann zu einer kompletten Integrations-Plattform ausgebaut werden, ohne dass die Grundlage gewechselt werden muss.
Architektur im Überblick
Der REST-Server besteht aus mehreren aufeinander aufbauenden Bausteinen, die alle in OBS gepflegt werden:
| Baustein | Tabelle | Zweck |
|---|---|---|
| Server | RESTSRV_SERVER | TLS-Profil + eigene HTTP-Server-Instanz, kann mehrfach existieren |
| Bindung | RESTSRV_BINDINGS | IP-Adresse + Port pro Server |
| Zugang | RESTSRV_ACCOUNT | API-Key, optionale Host- und CORS-Beschränkung, optionale JWT-Konfiguration |
| Endpunkt | RESTSRV_ENDPOINTS | Skript, das die Anfrage bearbeitet, einem Server fest zugeordnet |
| Berechtigung | RESTSRV_ACCESS | Verbindet Zugang und Endpunkt |
| Idempotenz | RESTSRV_IDEMPOTENCY | Speicher für Idempotency-Keys und die dazu gelieferte Antwort |
| Sitzung | RESTSRV_TOKEN | Ausgestellte Token-Paare je Sitzung; Grundlage für Rotation und Widerruf |
| Protokoll | RESTSRV_PROTO | Laufende Ereignisse, Fehler, Audit-Einträge |
| Statistik | RESTSRV_STATS | Aufrufzähler, Antwortzeiten und HTTP-Status pro Endpunkt |
Eine Anfrage durchläuft folgende Stationen:
- Rate-Limit-Prüfung (pro API-Key bzw. IP und global, Schwellen je Server-Profil)
- Andrangsgrenze des Server-Profils (Max. parallel) - bei Überschreitung 503 mit Retry-After
- Authentifizierung über den API-Key (Header apikey)
- CORS-Prüfung (sofern Origin-Header gesetzt)
- Optional: JWT-Prüfung - Signatur, Ablauf und Sitzung (sofern für den Zugang aktiviert)
- Routing: Auflösung des Pfads über die Pfad-Templates der Endpunkte
- Prüfung der Berechtigung (Zugang -> Endpunkt)
- Entpacken des Anfragekörpers, sofern er mit Content-Encoding: gzip gesendet wurde
- Idempotenz-Prüfung bei POST/PUT/PATCH/DELETE - der Header Idempotency-Key ist dort Pflicht
- Ausführung des Endpunkt-Skripts (oder WebHook-Antwort)
- Festschreiben des Ergebnisses im Idempotenz-Speicher (sofern in Schritt 9 reserviert)
- JSON-Antwort und Statistik-Eintrag
der Authentifizierung, damit ein Unbefugter dem Server keine Rechenzeit für eine Dekompressionsbombe abverlangen kann - und vor der Idempotenz-Reservierung, damit eine abgewiesene Anfrage keinen Idempotency-Key verbrennt.
Der Normalfall erzeugt keine Protokollzeile. Bis 08/2026 schrieb jede Anfrage eine Zeile nach RESTSRV_PROTO; sie ist entfallen, weil RESTSRV_STATS zu derselben Anfrage IP, Zugang, Endpunkt, Methode, Pfad, Status, Laufzeit und dieselbe Korrelations-ID trägt - und länger aufbewahrt wird. Das Protokoll trägt
seitdem nur noch Auffälligkeiten.Adressierung
Ein Endpunkt wird über ein Pfad-Template angesprochen, das den Pfad nach dem Host beschreibt und Platzhalter enthalten kann:
http://[Hostadresse][:Port][Pfad-Template]
Beispiele:
https://api.meinserver.de/kalender/v1 https://api.meinserver.de/orders/{uid} https://api.meinserver.de/orders/{uid}/modules/{code}
Statische Segmente müssen exakt passen; Platzhalter in geschweiften Klammern (z.B. {uid}) matchen einen beliebigen Wert und stehen im Skript als Pfad-Parameter zur Verfügung. Eine Versionskennung wird als statisches Segment ins Template aufgenommen (z.B. /kalender/v1), um eine Funktionalität zu verändern, ohne bestehende Konsumenten zu brechen. Details: Endpunkte.
Unterstützte HTTP-Methoden
Der Server akzeptiert die Methoden GET, POST, PUT, DELETE und PATCH sowie OPTIONS (CORS-Preflight, ohne Skript-Aufruf). Jede Methode wird im Endpunkt-Skript als gleichnamige Prozedur implementiert - mit einer Ausnahme: Delete ist in der Skriptsprache ein reservierter Name und lässt sich nicht als Prozedur deklarieren. Siehe Scripting.
Fehlt die zur Methode passende Prozedur, antwortet der Server mit 405 und nennt im Header Allow die Verben, die dieses Skript tatsächlich anbietet.
Kompression
Der Server packt Antworten mit gzip, wenn der Client sie annimmt. Ausgehandelt wird über den Anfrage-Header Accept-Encoding; die Antwort trägt dann Content-Encoding: gzip und Vary: Accept-Encoding - bei einer CORS-Anfrage steht dort Vary: Origin, Accept-Encoding, also eine Zeile mit beiden Bedingungen. Browser, curl --compressed und die gängigen HTTP-Bibliotheken entpacken selbstständig - für den Konsumenten ändert sich nichts ausser der übertragenen Datenmenge.
Gepackt wird nur, wo es etwas bringt:
- Nur JSON (auch problem+json und ndjson), XML, JavaScript, SVG und alles unter text/ - darunter Text, CSV und HTML. Bereits komprimierte Typen - PDF, Bild, ZIP, Video - werden durch gzip grösser, nicht kleiner.
- Erst ab 1024 Byte. Darunter kostet der gzip-Rahmen mehr, als der Inhalt einspart.
- Nicht bei Dateiantworten, nicht bei Teilauslieferungen (206) und nicht bei Antworten ohne Körper (204, 304).
- Nicht, wenn das Endpunkt-Skript den Header
Content-Encodingselbst gesetzt hat - dann gehört die Antwort dem Skript.
deflate wird in keiner Richtung unterstützt. Der Wert ist historisch uneindeutig - die einen senden RFC-1950-gerahmt, die anderen roh -, und wer ihn nennt, beherrscht ohnehin gzip. Eine Anfrage mit Content-Encoding: deflate wird mit 415 abgewiesen.
Abschalten lässt sich das Packen je Server-Profil über den Haken Keine Kompression (siehe Server-Profile). Der Haken betrifft ausschliesslich die Antwortrichtung.
Komprimierte Anfragen
In der Gegenrichtung nimmt der Server gzip entgegen: Trägt eine Anfrage den Header Content-Encoding: gzip, wird der Körper entpackt, bevor ihn jemand liest. Das Endpunkt-Skript merkt davon nichts.
| Anfrage | Antwort |
|---|---|
Content-Encoding fehlt oder identity |
normale Verarbeitung; ab 10 MB Körpergrösse 413 |
gzip |
Körper wird entpackt |
deflate, anderer Wert (z.B. br) oder mehrere Werte |
415 UNSUPPORTED_MEDIA_TYPE
|
| Gepackter Körper bei einem Datei-Upload | 415 - siehe Datei-Upload |
| Entpackter Körper über 10 MB | 413 PAYLOAD_TOO_LARGE
|
| Entpackter Körper über dem 400fachen der gesendeten Grösse | 413 PAYLOAD_TOO_LARGE
|
- 10 MB absolut. Dieselbe Grenze, die auch für einen ungepackten Körper gilt.
- das 400fache der gesendeten Grösse, mindestens aber 64 KB. Damit wird eine Dekompressionsbombe - wenige Kilobyte, die sich auf Hunderte Megabyte aufblähen - schon nach wenigen Prozent abgebrochen. Der Boden von 64 KB sorgt dafür, dass die Verhältnisrechnung winzige Körper gar nicht erst trifft: ein 100-Byte-Körper darf sich auf 64 KB entpacken, nicht nur auf 40 KB.
Die zweite Grenze trifft normale Nutzlasten nicht. Gemessen erreichen echte JSON-Körper Verhältnisse von 24:1 bis 40:1, und selbst eine Liste aus zehntausenden identischen Zeilen kommt nur auf rund 340:1 - mehr gibt das Verfahren für wiederholte Datensätze nicht her. Über 400:1 kommt nur, wer sehr lange Läufe desselben Zeichens sendet.
Für Datei-Uploads gilt keine der beiden Grenzen - dort zählt allein die je Endpunkt eingestellte Maximalgrösse.Persistente Verbindungen (Keep-alive)
Der Server hält eine Verbindung nach der Antwort offen, statt sie zu schliessen. Ein Client, der mehrere Anfragen hintereinander stellt - eine App, die eine Liste seitenweise abholt -, spart damit je Folgeanfrage den Aufbau von TCP-Verbindung und TLS-Sitzung.
| Grenze | Wert | Bedeutung |
|---|---|---|
| Leerlauf | 10 Sekunden | Passiert auf der Verbindung so lange nichts, wird sie geschlossen |
| Anfragen je Verbindung | 100 | Danach schliesst der Server geordnet, der Client baut neu auf |
Beides ist für den Konsumenten unkritisch: Eine geschlossene Verbindung ist kein Fehler, jede HTTP-Bibliothek baut sie bei der nächsten Anfrage selbst wieder auf. Wer viele Anfragen hintereinander stellt, gewinnt aber deutlich, wenn er seinen Client die Verbindung wiederverwenden lässt (Connection: keep-alive ist der Standard von HTTP/1.1, die meisten Bibliotheken tun es von allein).
nicht nur für das Warten auf die nächste Anfrage. Ein Client, der seinen Anfragekörper nur tropfenweise sendet und dazwischen länger als 10 Sekunden
pausiert, verliert die Verbindung mitten im Senden.Die Werte sind bewusst knapp gewählt: Der Server fährt einen eigenen Thread je Verbindung, eine leerlaufende Verbindung kostet also nicht bloss einen Dateizeiger. Sie sind keine Lastgrenze - dafür gibt es Max. Verbindungen und Max. parallel am Server-Profil (siehe Server-Profile).
Datei-Uploads
Endpunkte, die dafür freigeschaltet sind (re_upload), nehmen Dateien
per multipart/form-data oder als fortsetzbaren Resumable-Upload
(Content-Range) entgegen. Die maximale Grösse wird pro Endpunkt
festgelegt (re_upload_size, Standard 25 MB); Überschreitung
ergibt 413, ein Upload an einen nicht freigeschalteten Endpunkt 415. Der Server
legt die Datei temporär ab und übergibt dem Skript den Pfad; die weitere
Verarbeitung (z.B. DMS-Ablage) übernimmt das Skript. Details:
Scripting.
Doppelte Sendungen abfangen (Idempotenz)
Ein Client, der nach einem Timeout dieselbe Anfrage erneut schickt, darf keine
Zweitbuchung auslösen. Der Server erledigt das selbst: Jeder Aufruf mit
POST, PUT, PATCH oder DELETE muss den Header
Idempotency-Key tragen; der Server merkt sich Schlüssel und Ergebnis
in RESTSRV_IDEMPOTENCY. Eine Wiederholung mit demselben Schlüssel und
demselben Inhalt bekommt die gespeicherte Antwort zurück - das
Endpunkt-Skript läuft gar nicht erst an.
ohne Idempotency-Key wird mit 400
IDEMPOTENCY_KEY_MISSING abgewiesen, und das Endpunkt-Skript läuft
nicht an.
Das war bis v1.21 anders: fehlte der Header, lief die Anfrage ungeschützt durch. Der Schutz gegen eine Doppelbuchung stand damit in der Zusage des Clients und nicht in einer Prüfung des Servers - ein Wiederholversuch nach Zeitüberschreitung buchte ein zweites Mal. Konsumenten, die bisher ohne den Header schreiben, müssen
angepasst werden.- Pflicht nur für schreibende Verben. GET braucht keinen Schlüssel und kennt die Mechanik nicht.
- Der JWT-Endpunkt ist ausgenommen. Anmelden, Erneuern und Abmelden laufen vor der Adressauflösung und brauchen keinen Schlüssel.
- Kein Schalter am Endpunkt. Die Mechanik greift für jeden Endpunkt automatisch.
- Das Skript muss nichts tun. Eine eigene Idempotenz-Logik im Skript ist nicht nötig.
- Pro Vorgang ein Schlüssel, über alle Wiederholversuche hinweg unverändert - nicht bei jedem Versuch neu erzeugt.
Details und die Statuscodes: Endpunkte, Abschnitt Idempotenz.
Sitzungen und Abmelden
Ein JWT trägt seine Gültigkeit in sich: der Server prüft Signatur und Ablauf und braucht dafür keine Datenbank. Genau deshalb liesse sich ein ausgegebener Token von sich aus auch nicht mehr zurückziehen - ein verlorenes Gerät wäre bis zum Ablauf des Tokens weiter nutzbar.
Der Server führt deshalb zu jedem ausgestellten Token-Paar eine Zeile in RESTSRV_TOKEN und prüft jeden Zugriff dagegen. Daraus ergeben sich drei Eigenschaften:
- Abmelden wirkt sofort. Ein DELETE auf den JWT-Endpunkt sperrt die Sitzung; alle Token dieser Sitzung sind damit unmittelbar ungültig, auch die noch nicht abgelaufenen. Anmelden, Erneuern und Abmelden laufen also über einen einzigen Endpunkt, und für das Abmelden ist kein Skript nötig.
- Ein Refresh-Token gilt genau einmal. Beim Erneuern wird es entwertet. Wird es später erneut vorgelegt, gilt das als Diebstahl oder Fehlfunktion: die betroffene Sitzung wird komplett gesperrt und der Vorfall protokolliert.
- Alle Geräte abmelden. Ein gewöhnlicher Endpunkt kann über den Aufruf oWriter.JwtRevoke('all') auch alle Sitzungen eines Benutzers sperren - der Support-Fall „Gerät verloren".
ausgestellten Token ihre Gültigkeit, weil sie zu keiner Sitzung gehören.
Angemeldete Konsumenten müssen sich nach dem Update einmalig neu anmelden.Der Speicher pflegt sich selbst: Zeilen werden gelöscht, sobald sowohl das Access- als auch das Refresh-Token abgelaufen sind. Details und die Skript-Seite: Zugänge.
Fehlerformat
Jede Fehlerantwort des Servers hat dieselbe Form: ein einziges error-Objekt mit maschinenlesbarem Code, Support-Kennung, Meldung und Korrelations-ID:
{
"error": {
"code": "AUTH_EXPIRED",
"uid": "Y00E2RTPDY",
"message": "Ungültiges oder abgelaufenes Token",
"traceId": "20260817T091233123-00001A"
}
}
- code - sprechender Bezeichner (z.B. AUTH_EXPIRED, NOT_FOUND, RATE_LIMITED, INTERNAL_ERROR), an dem ein Client seine Reaktion festmachen kann, ohne Texte auszuwerten.
- uid - OBS-Kennung der Codestelle. Für die Support-Recherche gedacht, nicht zur Auswertung im Client.
- message - Text für den Client. Interne Fehlerdetails stehen nie darin, sondern ausschliesslich im Protokoll RESTSRV_PROTO.
- traceId - Korrelations-ID. Steht zusätzlich im Header X-Trace-Id und in jeder zugehörigen Logzeile.
Ein Endpunkt-Skript kann eigene Codes setzen; siehe Scripting.
error-Objekt, nicht flach daneben - der Wert von Fehlercode heisst jetzt error.uid, Nachricht entspricht error.message. Clients, die die flachen Felder auswerten, müssen angepasst
werden.Sicherheitsmerkmale
Der REST-Server enthält eine Reihe von Schutzmechanismen:
- Rate-Limit: Standardmässig max. 10 fehlgeschlagene und 120 erfolgreiche Anfragen pro API-Key (Account) bzw. IP und 60 Sekunden, max. 600 Anfragen global pro 60 Sekunden. Beim Überschreiten wird HTTP 429 mit Retry-After-Header zurückgegeben. Die vier Schwellen lassen sich pro Server-Profil hinterlegen; die Zähler laufen ebenfalls getrennt je Profil, ein überlastetes Profil bremst das andere also nicht mit aus. Siehe Server-Profile.
- Body-Limit: max. 10 MB Request-Body (JSON), max. 1024 Zeichen pro Header- oder Query-Parameter. Datei-Uploads laufen über einen separaten Pfad und sind pro Endpunkt auf
re_upload_sizeMB begrenzt (Standard 25 MB). - Sensible Felder (password, token, secret, apikey, authorization, cookie, ...) werden in Protokoll-Ausgaben automatisch maskiert.
- Widerrufbare Token: Jedes ausgestellte Token-Paar gehört zu einer Sitzung in RESTSRV_TOKEN und wird bei jedem Zugriff dagegen geprüft. Eine Abmeldung wirkt damit sofort und nicht erst mit dem Ablauf des Tokens; ein Refresh-Token gilt genau einmal. Siehe Zugänge.
- Reserviertes Präfix: Parameter-Namen mit Präfix _OBS_ können von aussen nicht gesetzt werden, sie sind für den Server reserviert (z.B. JWT-Claims).
- Geblockte Header: authorization, cookie, proxy-authorization, x-forwarded-for, x-real-ip, apikey, api_key werden nicht an das Skript durchgereicht.
- TLS: Bei Profilen mit aktivem TLS fährt der Server ohne Zertifikat und Key nicht hoch. Plain-HTTP ist nur für ein dediziertes Debug-Profil möglich.
- HSTS: Antworten eines TLS-Profils tragen Strict-Transport-Security: max-age=31536000; includeSubDomains. Ein Browser spricht die Adresse danach ein Jahr lang nur noch über HTTPS an. Beim Debug-Profil Kein SSL wird der Header bewusst nicht gesetzt - der Browser würde ihn sonst speichern und die Erzwingung auch auf produktive Sitzungen anwenden.
- mTLS (Mutual TLS): erzwingt, dass jeder Client ein gültiges Client-Zertifikat vorlegt. Optional kann pro Zugang ein erwarteter Subject-DN hinterlegt werden.
- DNS-Cache: Host-zu-IP-Auflösungen für die Zugangs-Host-Prüfung werden 5 Minuten gecached.
Protokoll
Die Tabelle RESTSRV_PROTO enthält alle relevanten Ereignisse: erfolgreiche und abgelehnte Anfragen, TLS-/JWT-Fehler, Bindungs-Ereignisse, Skript-Fehler. Einträge sind nach Datum, Uhrzeit und Host (IP oder Account-Name) sortiert. Das Protokoll ist die erste Anlaufstelle bei Störungen. Jede Antwort trägt zudem eine Korrelations-ID (Response-Header X-Trace-Id), die in den Protokoll-Einträgen wiederzufinden ist.
Statistik
Die Tabelle RESTSRV_STATS enthält eine Statistik aller bearbeiteten Anfragen mit IP, Zugang, Endpunkt, Methode, angefragtem Pfad, HTTP-Status und Laufzeit in Millisekunden. Dazu kommen zwei Felder, die den Sprung ins Protokoll erlauben:
- rs_trace - dieselbe Korrelations-ID, die auch im Header X-Trace-Id und in jeder zugehörigen Protokollzeile steht. Damit findet man zu einer auffälligen Statistikzeile alle Protokolleinträge derselben Anfrage.
- rs_server - das Server-Profil, über das die Anfrage hereinkam. Bei mehreren Profilen (Public-TLS neben Internal-mTLS) ist das die einzige Angabe, an der sich der Weg ablesen lässt.
Weil der Normalfall keine Protokollzeile mehr schreibt, ist RESTSRV_STATS die vollständige Sicht auf den Betrieb - RESTSRV_PROTO die auf die Auffälligkeiten.
Aufruf der Statistik:
- Aus der Endpunkt-Liste: F8 zeigt die Statistik des markierten Endpunkts.
- Aus der Zugänge-Liste: F8 zeigt die Statistik des markierten Zugangs.
Konsole
Wird der REST-Server nicht als Dienst, sondern interaktiv gestartet, erscheint eine farbige Konsole mit Live-Log und einem fixierten Kopfbereich, der die gerade laufenden Anfragen zeigt und sich fortlaufend aktualisiert.
| Befehl | Wirkung |
|---|---|
| show <handle> | Details einer Anfrage: Request-Header, Protokollzeilen, Antwort. JSON wird farbig formatiert. <handle> ist die Kennung aus der Abschlusszeile der Anfrage (z.B. 7F), keine laufende Nummer |
| 1 … 9 | Auswahl im Kopfbereich - kürzer als show für die gerade sichtbaren Anfragen. Mit mouse on auch per Klick |
| ps | Listet die gerade laufenden Anfragen auf |
| level <stufe> | Anzeigestufe des Live-Logs: quiet , normal oder debug. Ohne Parameter wird die aktuelle Stufe genannt |
| filter <ausdruck> | Blendet aus, was nicht passt: path=<text>, account=<name>, status>=. filter aus hebt die Einschränkung auf
|
| panel on|off | Fixierten Kopfbereich ein-/ausschalten. Ausgeschaltet lässt sich der Rückblick-Puffer des Konsolenfensters wieder scrollen |
| mouse on|off | Klick-Auswahl im Kopfbereich. Eingeschaltet ist das Markieren von Text mit der Maus nicht mehr möglich |
| help / ? | Zeigt diese Liste in der Konsole |
| exit / quit | Beendet den Server geordnet |
Im Service-Modus (Windows-Dienst) ist die Konsole nicht sichtbar. Alle Einträge landen dort ausschliesslich in der Tabelle RESTSRV_PROTO.
Weiterführende Seiten
- Einrichtung - Schritt-für-Schritt-Anleitung
- Server-Profile - TLS, mTLS und Bindungen
- Zugänge - API-Keys, JWT, CORS, Host-Beschränkung
- Endpunkte - Verwaltung, Berechtigungen, WebHooks
- Scripting - Aufbau der Endpunkt-Skripte
- Datei-Upload - Übertragungsprotokoll für Dateien (Multipart, resumable)
- Datei-Download - Dateien ausliefern, Range/Resume, öffentliche Artefakte
- Beispiel 1: Daten-Abruf mit JWT
- Beispiel 2: Zeiterfassung als komplette Webanwendung
- Beispiel 3: Datensatz anlegen mit JSON-Body (CRUD)
- Beispiel 4: Pfad-Parameter im Routing
- Beispiel 5: Schreibzugriff mit Statuscodes, ETag und Idempotenz
- Beispiel 6: Datei-Upload und Ablage im DMS