Asset Manager API
Einleitung
Das Asset Manager API ist ein schreibgeschütztes HTTP-API zum Lesen von Daten aus einem SQL Server.
Es handelt sich nicht um ein klassisches REST-API.
Bei einem klassischen REST-API sind die Datenstrukturen normalerweise fest bekannt. Es gibt zum Beispiel feste Endpunkte wie:
GET /api/customers
GET /api/orders
GET /api/products
Das API kennt dabei die Tabellen, Spalten und Datenmodelle bereits zur Entwicklungszeit.
Bei diesem API ist das anders. Die Datenbank des Asset Managers wird kundenseitig dynamisch definiert. Das bedeutet:
- Es ist vorher nicht bekannt, welche Tabellen existieren.
- Es ist vorher nicht bekannt, welche Views existieren.
- Es ist vorher nicht bekannt, welche Spalten eine Tabelle oder View hat.
- Das API kann deshalb keine festen Endpunkte pro Datenobjekt anbieten.
Darum muss zuerst abgefragt werden, welche Tabellen oder Views vorhanden sind. Danach werden die Spalten dieser Objekte ermittelt. Erst mit diesem Wissen können gezielt Daten gelesen werden.
Der typische Ablauf ist:
1. Verfügbare Tabellen oder Views abrufen
2. Spalten einer Tabelle oder View abrufen
3. Optional Anzahl der Datensätze abrufen
4. Daten mit Spaltenauswahl, Sortierung, Paging und Filtern lesen
Grundprinzip
Das API liest Metadaten aus SQL Server und verwendet diese Informationen zur Validierung.
Alle übergebenen Namen werden gegen SQL-Server-Metadaten geprüft:
- Schema
- Tabelle
- View
- Spalten
- Sortierspalten
- Filterspalten
Rohe SQL-Fragmente werden nicht akzeptiert.
Dadurch kann das API dynamisch arbeiten, ohne beliebige SQL-Befehle von außen auszuführen.
Authentifizierung
Das API verwendet einen API-Key im HTTP-Header.
Der Headername wird im System über X-API-Key festgelegt.
Beispiel:
X-API-Key: <your-api-key>
Einschränkungen
Das API ist absichtlich eingeschränkt:
| Einschränkung | Bedeutung |
|---|---|
| Nur lesender Zugriff | Es gibt keine Endpunkte zum Erstellen, Ändern oder Löschen von Daten. |
take muss zwischen 1 und 1000 liegen |
Pro Anfrage können maximal 1000 Zeilen gelesen werden. |
skip muss 0 oder größer sein |
Negative Werte sind nicht erlaubt. |
skip > 0 benötigt orderBy |
Paging ohne feste Sortierung wäre instabil. |
| Keine rohen SQL-Fragmente | SQL-Teile wie WHERE 1=1 oder DROP TABLE werden nicht als Parameter akzeptiert. |
Endpunkte
GET /api/help
Gibt ein Hilfedokument des API zurück.
Parameter
Keine
Beispiel
GET /api/help
Zweck
Dieser Endpunkt zeigt:
- Name des API
- Beschreibung
- Authentifizierung
- Einschränkungen
- verfügbare Routen
- Beispielparameter
- Beispielantworten
GET /api/views
Gibt alle verfügbaren SQL-Server-Views zurück.
Parameter
Keine
Beispiel
GET /api/views
Beispielantwort
[
{
"Schema": "dbo",
"Name": "CustomerOverview"
},
{
"Schema": "dbo",
"Name": "OpenOrders"
}
]
Verwendung
Dieser Endpunkt wird verwendet, um herauszufinden, welche Views verfügbar sind.
Eine View kann anschließend wie eine Tabelle über /api/columns, /api/count und /api/data verwendet werden.
GET /api/tables
Gibt alle verfügbaren SQL-Server-Tabellen zurück.
Parameter
Keine
Beispiel
GET /api/tables
Beispielantwort
[
{
"Schema": "dbo",
"Name": "Customers"
},
{
"Schema": "dbo",
"Name": "Orders"
}
]
Verwendung
Dieser Endpunkt wird verwendet, um herauszufinden, welche Tabellen über das API gelesen werden können.
GET /api/columns
Gibt alle Spalten einer ausgewählten Tabelle oder View zurück.
Parameter
| Parameter | Pflicht | Beschreibung |
|---|---|---|
schema |
Ja | Name des SQL-Schemas, zum Beispiel dbo. |
table |
Ja | Name der SQL-Tabelle oder View, zum Beispiel Customers oder CustomerOverview. |
Beispiel
GET /api/columns?schema=dbo&table=Customers
Beispielantwort
[
{
"Name": "Id",
"StoreType": "int",
"Nullable": false,
"Ordinal": 1
},
{
"Name": "Name",
"StoreType": "nvarchar",
"Nullable": true,
"Ordinal": 2
}
]
Felder der Antwort
| Feld | Bedeutung |
|---|---|
Name |
Name der Spalte |
StoreType |
SQL-Datentyp der Spalte |
Nullable |
Gibt an, ob die Spalte NULL enthalten darf |
Ordinal |
Position der Spalte in der Tabelle oder View |
Verwendung
Dieser Endpunkt wird vor /api/data verwendet.
So wird ermittelt, welche Spalten über die Parameter columns, orderBy oder filters verwendet werden können.
GET /api/count
Gibt die Anzahl der Datensätze einer Tabelle oder View zurück.
Parameter
| Parameter | Pflicht | Beschreibung |
|---|---|---|
Schema |
Ja | Name des SQL-Schemas, zum Beispiel dbo. |
Table |
Ja | Name der SQL-Tabelle oder View, zum Beispiel Customers oder CustomerOverview. |
Beispiel
GET /api/count?Schema=dbo&Table=Customers
Beispielantwort
{
"Schema": "dbo",
"Table": "Customers",
"Count": 42
}
Verwendung
Dieser Endpunkt ist nützlich für:
- Anzeige der Gesamtanzahl
- Vorbereitung von Paging
- Prüfung, ob eine Tabelle oder View Daten enthält
GET /api/data
Gibt Zeilen einer Tabelle oder eines Views als gestreamtes JSON zurück.
Dieser Endpunkt ist der zentrale Datenlese-Endpunkt.
Vor der Abfrage werden validiert:
- Schema
- Tabelle oder View
- ausgewählte Spalten
- Sortierspalten
- Filterspalten
Parameter
| Parameter | Pflicht | Standard | Beschreibung |
|---|---|---|---|
schema |
Ja | - | Name des SQL-Schemas, zum Beispiel dbo. |
table |
Ja | - | Name der Tabelle oder View, zum Beispiel Customers. |
columns |
Nein | * |
Kommaseparierte Spaltenliste. Mit * oder ohne Parameter werden alle Spalten zurückgegeben. |
orderBy |
Nein | - | Spalte oder kommaseparierte Spaltenliste für die Sortierung. Erforderlich, wenn skip > 0 ist. |
sort |
Nein | asc |
Sortierrichtung. Erlaubt sind asc und desc. |
take |
Nein | 100 |
Maximale Anzahl der Zeilen. Erlaubt sind Werte von 1 bis 1000. |
skip |
Nein | 0 |
Anzahl der zu überspringenden Zeilen. Bei Werten größer als 0 ist orderBy erforderlich. |
filters |
Nein | - | Kommaseparierte Filter im Format Spalte:Operator:Wert. Mehrere Filter werden mit AND verknüpft. |
Spaltenauswahl
Alle Spalten lesen
GET /api/data?schema=dbo&table=Customers&columns=*
Der Parameter columns=* bedeutet: alle Spalten zurückgeben.
Der Parameter kann auch weggelassen werden. Dann werden ebenfalls alle Spalten zurückgegeben.
Bestimmte Spalten lesen
GET /api/data?schema=dbo&table=Customers&columns=Id,Name
In diesem Beispiel werden nur die Spalten Id und Name gelesen.
Die Spaltennamen müssen in der Tabelle oder View existieren.
Sortierung
Einfache Sortierung
GET /api/data?schema=dbo&table=Customers&orderBy=Id
Standardmäßig wird aufsteigend sortiert.
Das entspricht:
GET /api/data?schema=dbo&table=Customers&orderBy=Id&sort=asc
Absteigende Sortierung
GET /api/data?schema=dbo&table=Customers&orderBy=Id&sort=desc
Sortierung nach mehreren Spalten
GET /api/data?schema=dbo&table=Customers&orderBy=manufacturer,product,version
Die Sortierspalten werden in der angegebenen Reihenfolge verwendet.
Paging
Paging bedeutet: Daten werden seitenweise gelesen.
Dafür werden take, skip und orderBy verwendet.
Erste Seite
GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=0
Bedeutung:
- Maximal 100 Zeilen lesen.
- Keine Zeilen überspringen.
- Nach
Idsortieren.
Zweite Seite
GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=100
Bedeutung:
- Die ersten 100 Zeilen überspringen.
- Danach maximal 100 Zeilen lesen.
Wichtige Regel
Sobald skip größer als 0 ist, muss orderBy angegeben werden.
Grund: Ohne feste Sortierung kann SQL Server die Reihenfolge der Zeilen ändern. Dann wäre Paging nicht stabil.
Filter
Filter werden über den Parameter filters angegeben.
Format:
Spalte:Operator:Wert
Mehrere Filter werden mit Komma getrennt:
Spalte1:Operator:Wert,Spalte2:Operator:Wert
Mehrere Filter werden mit AND verbunden.
Beispiel
GET /api/data?schema=dbo&table=Orders&columns=OrderId&filters=Status:eq:Open,Amount:gt:100&orderBy=OrderId
Bedeutung:
Status = Open
AND Amount > 100
Es wird nur die Spalte OrderId zurückgegeben.
Erlaubte Filteroperatoren
| Operator | SQL-Vergleich | Bedeutung |
|---|---|---|
eq |
= |
Gleich |
ne |
<> |
Ungleich |
gt |
> |
Größer als |
gte |
>= |
Größer oder gleich |
lt |
< |
Kleiner als |
lte |
<= |
Kleiner oder gleich |
like |
LIKE |
SQL-LIKE-Vergleich |
LIKE-Filter
Für Textsuche kann like verwendet werden.
Beispiel:
GET /api/data?schema=dbo&table=Customers&filters=Name:like:M%25&orderBy=Name&sort=asc&take=50
%25 ist die URL-kodierte Form von %.
Der Filter entspricht sinngemäß:
Name LIKE 'M%'
Damit werden Namen gefunden, die mit M beginnen.
Beispielablauf
1. Tabellen abrufen
GET /api/tables
Beispielantwort:
[
{
"Schema": "dbo",
"Name": "Customers"
}
]
Jetzt ist bekannt, dass es die Tabelle dbo.Customers gibt.
2. Spalten der Tabelle abrufen
GET /api/columns?schema=dbo&table=Customers
Beispielantwort:
[
{
"Name": "Id",
"StoreType": "int",
"Nullable": false,
"Ordinal": 1
},
{
"Name": "Name",
"StoreType": "nvarchar",
"Nullable": true,
"Ordinal": 2
}
]
Jetzt ist bekannt, dass die Spalten Id und Name verfügbar sind.
3. Anzahl der Datensätze abrufen
GET /api/count?Schema=dbo&Table=Customers
Beispielantwort:
{
"Schema": "dbo",
"Table": "Customers",
"Count": 42
}
4. Daten lesen
GET /api/data?schema=dbo&table=Customers&columns=Id,Name&orderBy=Id&take=100&skip=0
Beispielantwort:
[
{
"Id": 1,
"Name": "Mueller"
},
{
"Id": 2,
"Name": "Schmidt"
}
]
Weitere Beispiele für /api/data
Alle Spalten lesen
GET /api/data?schema=dbo&table=Customers&columns=*&orderBy=Id&take=100&skip=0
Nur bestimmte Spalten lesen
GET /api/data?schema=dbo&table=Customers&columns=Id,Name&orderBy=Id&take=100&skip=0
Nach mehreren Spalten sortieren
GET /api/data?schema=dbo&table=Customers&columns=*&orderBy=manufacturer,product,version&take=100&skip=0
Mit mehreren Filtern lesen
GET /api/data?schema=dbo&table=Orders&columns=OrderId&filters=Status:eq:Open,Amount:gt:100&orderBy=OrderId
LIKE-Suche verwenden
GET /api/data?schema=dbo&table=Customers&filters=Name:like:M%25&orderBy=Name&sort=asc&take=50
Sicherheit und Validierung
Das API schützt sich dadurch, dass Eingaben nicht direkt als SQL übernommen werden.
Stattdessen wird geprüft, ob die angegebenen Objekte wirklich existieren:
| Eingabe | Prüfung |
|---|---|
schema |
Muss als SQL-Schema existieren. |
table |
Muss als Tabelle oder View existieren. |
columns |
Jede angeforderte Spalte muss existieren. |
orderBy |
Jede Sortierspalte muss existieren. |
filters |
Jede Filterspalte muss existieren. |
| Filteroperator | Muss einer der erlaubten Operatoren sein. |
Nicht erlaubt sind direkte SQL-Fragmente wie:
Id; DROP TABLE Customers
Name ASC; DELETE FROM Orders
1=1
Das API erwartet strukturierte Parameter, keine SQL-Befehle.
Typische Fehlerquellen
Tabelle oder View nicht vorher geprüft
Falsch:
GET /api/data?schema=dbo&table=Irgendwas
Richtig:
GET /api/tables
GET /api/views
Danach mit einem vorhandenen Objekt weiterarbeiten.
Spalte existiert nicht
Falsch:
GET /api/data?schema=dbo&table=Customers&columns=CustomerName
Richtig:
GET /api/columns?schema=dbo&table=Customers
Danach nur vorhandene Spalten verwenden.
Paging ohne Sortierung
Falsch:
GET /api/data?schema=dbo&table=Customers&take=100&skip=100
Richtig:
GET /api/data?schema=dbo&table=Customers&orderBy=Id&take=100&skip=100
Zu viele Zeilen angefordert
Falsch:
GET /api/data?schema=dbo&table=Customers&take=5000
Richtig:
GET /api/data?schema=dbo&table=Customers&take=1000
take darf maximal 1000 sein.
Zusammenfassung
Das Asset Manager API dient zum sicheren, lesenden Zugriff auf dynamisch definierte SQL-Server-Tabellen und Views.
Der wichtigste Unterschied zu einem klassischen REST-API ist, dass die Datenstruktur nicht fest im Programm bekannt ist. Deshalb müssen Tabellen, Views und Spalten zuerst über Metadaten-Endpunkte abgefragt werden.
Empfohlener Ablauf:
/api/tables oder /api/views
/api/columns
/api/count
/api/data
Das API erlaubt nur lesende Zugriffe, validiert alle Objekt- und Spaltennamen gegen SQL-Server-Metadaten und akzeptiert keine rohen SQL-Fragmente.